为什么 ceil() 对没有小数部分的偶数浮点数进行四舍五入?
当我尝试这样做时:
double x = 2.22;
x *= 100; //which becomes 222.00...
printf("%lf", ceil(x)); //prints 223.00... (?)
但是当我将 2.22 的值更改为 2.21
x *= 100; //which becomes 221.00...
printf("%lf", ceil(x)); //prints 221.00... as expected
我尝试使用 modf() 以另一种方式进行操作,并遇到了另一个奇怪的事情:
double x = 2.22 * 100;
double num, fraction;
fraction = modf(x, &num);
if(fraction > 0)
num += 1; //goes inside here even when fraction is 0.00...
那么会发生什么 0.000...大于 0?
谁能解释为什么会发生这两种情况?我还在 RedHat 中使用 cc 版本 4.1.2 进行编译。
double x = 2.22;
实际上比值
2.22
稍大一点,而你用
得到的值
double x = 2.21;
比
2.21
小一点点。
float
和
double
C 类型正确表示 - 最有可能的是您认为的 222
实际上类似于 222.00000000000000001
。有一个标准但鲜为人知的方法来解决它 - 使用
nextafter()
C99 函数:
printf("%lf", ceil(nextafter(x, 0)));
详情请参阅
man nextafter
。
double x = 2.22;
printf("%.20lf\n", x); //prints 2.22000000000000019540
x *= 100;
printf("%.20lf\n", x); //prints 222.00000000000002842171
如果您需要整数精度(例如计算金钱相关的东西),请使用积分算术(即计算美分而不是美元)。
const int x = 1.2;
在 C 程序中,会发生什么? 文字
1.2
不能表示为整数值,因此编译器会根据通常的规则转换为整数,并且
x
将被分配值 1
。同样的事情也发生在这里。
你写道:
double x = 2.22;
2.22
不能表示为双精度数,因此编译器根据 C 标准中的规则对其进行转换。 您得到最接近的可表示双精度数,这正是:
2.220000000000000195399252334027551114559173583984375
当这个值在
double
中乘以100时,结果是:
222.000000000000028421709430404007434844970703125
当您使用该值作为参数调用
ceil( )
时,数学库会正确返回
223.0
。