主页C++ Builder 资料C++ Builder 参考手册System.Math.hpp 数学函数RoundTo
C++ Builder 串口控件
C++ Builder 编程技巧
C++ Builder 操作指南
C++ Builder 参考手册
基础知识
cfloat 浮点数
cmath 数学函数
cstdlib 标准库函数
System 字符串
System 日期和时间
System.Math.hpp 数学函数
 • RoundTo
 • SetExceptionMask
 • TArithmeticException
 • TArithmeticExceptionMask
 • DefaultExceptionFlags
 • exAllArithmeticExceptions
其他数据类型
VCL 基础类
VCL 应用程序
Pictures 图片
Graphics 绘图
Additional 控件
System 控件
A ~ Z 字母顺序排列的目录
网友留言/技术支持
RoundTo - 使用 “四舍六入五成双” 的 Banker's Rounding 规则截取浮点数

RoundTo: 使用 “四舍六入五成双” 的 Banker's Rounding 规则截取浮点数

函数原型:

typedef Int8 TRoundToEXRangeExtended;
Extended __fastcall RoundTo(const Extended AValue, const TRoundToEXRangeExtended ADigit);

头文件:

#include <System.Math.hpp>

命名空间:

System::Math

参数:

AValue:需要截取的浮点数,long double 类型的长浮点数。
ADigit:截取的位数,8 位整数,范围:-20 ~ 20

返回值:

ADigit = 0:返回值为取整的值,
ADigit < 0:返回值为小数点后保留 ADigit 位
ADigit > 0:返回值为取整并且整数部分低 ADigit 位清零

运算 说明
RoundTo(1234567.89 , 3) 1235000 取整并且整数部分低 3 位清零,清掉的 567.89 偏向进位方向,进位
RoundTo( 2.4999, 0) 2 取整,清掉的 4999 偏向于舍弃方向,舍弃
RoundTo( 2.5 , 0) 2 取整,清掉的 5 在中间位置,取偶数方向,舍弃
RoundTo( 2.5001, 0) 3 取整,清掉的 5001 偏向于进位方向,进位
RoundTo( 1.234 , -2) 1.23 小数部分保留 2 位,清掉的 4 偏向于舍弃方向,舍弃
RoundTo( 1.235 , -2) 1.24 小数部分保留 2 位,清掉的 5 在中间位置,取偶数方向,进位
RoundTo( 1.625 , -2) 1.62 小数部分保留 2 位,清掉的 5 在中间位置,取偶数方向,舍弃
RoundTo( 1.245 , -2) 1.25 由于浮点数 1.245 无法用二进制数据精确的表示出来,在电脑里面的二进制数据实际上是用 1.24500000000000011 来表示 1.245 的,清掉的 500000000000011 偏向于进位方向,进位

RoundTo 函数使用 “四舍六入五成双” 的 Banker's Rounding 规则 (五后有数入、五后无数凑偶数),和传统的 “四舍五入” 的区别为:

根据上面的图形可以看到:传统的 “四舍五入” 会让数量非常大的数据计算之后偏大,因为两端距离相等的时候始终选择绝对值大的,而 “四舍六入五成双” 的 Banker's Rounding 规则会让数据两端取舍的概率均等,因为对于不同的数值,偶数可能在左边,也可能在右边,计算之后的数据不会明显偏大或偏小,所以与 std::round 相比,更推荐使用 System::Math::RoundTo 函数。看下面的例子对取舍规则会有更详细的了解。

例子:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  const wchar_t fmt[] = L"%6.2f %6.2f %6.2f %6.2f %6.2f %6.2llf\r\n";
  UnicodeString s = L" value  trunc  floor   ceil  round  RoundTo\r\n";
  s.cat_sprintf(fmt,  5.4 , trunc( 5.4 ), floor( 5.4 ), ceil( 5.4 ), round( 5.4 ), RoundTo( 5.4 ,0));
  s.cat_sprintf(fmt,  5.5 , trunc( 5.5 ), floor( 5.5 ), ceil( 5.5 ), round( 5.5 ), RoundTo( 5.5 ,0));
  s.cat_sprintf(fmt,  6.5 , trunc( 6.5 ), floor( 6.5 ), ceil( 6.5 ), round( 6.5 ), RoundTo( 6.5 ,0));
  s.cat_sprintf(fmt,  6.51, trunc( 6.51), floor( 6.51), ceil( 6.51), round( 6.51), RoundTo( 6.51,0));
  s.cat_sprintf(fmt,  6.8 , trunc( 6.8 ), floor( 6.8 ), ceil( 6.8 ), round( 6.8 ), RoundTo( 6.8 ,0));
  s.cat_sprintf(fmt, -5.4 , trunc(-5.4 ), floor(-5.4 ), ceil(-5.4 ), round(-5.4 ), RoundTo(-5.4 ,0));
  s.cat_sprintf(fmt, -5.5 , trunc(-5.5 ), floor(-5.5 ), ceil(-5.5 ), round(-5.5 ), RoundTo(-5.5 ,0));
  s.cat_sprintf(fmt, -6.5 , trunc(-6.5 ), floor(-6.5 ), ceil(-6.5 ), round(-6.5 ), RoundTo(-6.5 ,0));
  s.cat_sprintf(fmt, -6.51, trunc(-6.51), floor(-6.51), ceil(-6.51), round(-6.51), RoundTo(-6.51,0));
  s.cat_sprintf(fmt, -6.8 , trunc(-6.8 ), floor(-6.8 ), ceil(-6.8 ), round(-6.8 ), RoundTo(-6.8 ,0));
  Memo1->Lines->Text = s;
}

相关链接:

ceilfloortruncround_matherr浮点数异常处理

下一页:SetExceptionMask

C++ 爱好者 -- Victor Chen 的个人网站 www.cppfans.com 辽ICP备11016859号