math.h ceil在C中没有按预期工作

boj*_*oja 6 c compiler-construction math floating-point

为什么ceil()会在没有分数部分的情况下进行均匀浮动?
当我尝试这样做时:

double x = 2.22;  
x *= 100; //which becomes 222.00...  
printf("%lf", ceil(x)); //prints 223.00... (?)  
Run Code Online (Sandbox Code Playgroud)

但是当我将2.22的值更改为2.21时

x *= 100; //which becomes 221.00...  
printf("%lf", ceil(x)); //prints 221.00... as expected  
Run Code Online (Sandbox Code Playgroud)

我尝试用另一种方式使用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...  
Run Code Online (Sandbox Code Playgroud)

那么会发生什么是0.000 ...大于0?
谁能解释为什么这两种情况都会发生?此外,我正在使用RedHat中的cc版本4.1.2进行编译.

Dan*_*tin 12

基本答案是你得到的浮点数:

double x = 2.22;
Run Code Online (Sandbox Code Playgroud)

实际上比值大一点2.22,以及你得到的值

double x = 2.21;
Run Code Online (Sandbox Code Playgroud)

比一点点小2.21.


Gor*_*kic 12

这是正常的,因为使用二进制存储数字.虽然您的数字可以使用十进制数字写入有限数字,但这不适用于二进制数字.

您应该阅读Goldberg的报告,称为每个计算机科学家应该知道的关于浮点算术的内容.

  • 每个人总是指着那篇文章,但它并不好.你最好阅读维基百科 (2认同)

qrd*_*rdl 7

并非所有的浮点值,可以通过正确地代表floatdoubleC型-最有可能你在想什么是222真正喜欢的东西222.00000000000000001.

有一种标准的,但鲜为人知的解决方法 - 使用nextafter()C99功能:

printf("%lf", ceil(nextafter(x, 0)));
Run Code Online (Sandbox Code Playgroud)

详情man nextafter请见.

  • 有趣!另见'nearbyint'和'rint'. (3认同)