6

我一直在尝试天花板功能,并得到了一些奇怪的结果。如果我对乘以百的十进制数执行 ceil 运算,我会得到一定的结果。但是,如果我直接对该乘法的结果执行 ceil ,我会得到完全不同的输出。另一个转折是这些不同的结果只发生在某些数字上。任何帮助,将不胜感激。

#include <stdio.h>
#include <cmath>

int main ()
{
cout << "The ceiling of " << 411 << " is " << ceil(411) << endl;
cout << "The ceiling of 4.11*100  is " << ceil(4.11*100) << endl;

cout << "The ceiling of  " << 121 << " is " << ceil(121) << endl;
cout << "The ceiling of 1.21*100  is " << ceil(1.21*100) << endl;;
}


OUTPUT:

The ceiling of 411 is 411
The ceiling of 4.11*100  is 412
The ceiling of  121 is 121
The ceiling of 1.21*100  is 121
4

3 回答 3

9

这里的问题是浮点数不能被计算机可靠地表示。这意味着,4.11不表示为4.11,而是非常接近它的东西。而当这个“非常接近 4.11”的数字乘以 时100ceil结果是412,让您大吃一惊!但是,一旦您知道浮点数是如何存储和检索的,就不足为奇了。


看看这个有趣的演示:

float a = 3.2; //3.2 is double!
if ( a == 3.2 )
    cout << "a is equal to 3.2"<<endl;
else
    cout << "a is not equal to 3.2"<<endl;

float b = 3.2f; //3.2f is a float. Note: f is appended to make it float!
if ( b == 3.2f )
    cout << "b is equal to 3.2f"<<endl;
else
    cout << "b is not equal to 3.2f"<<endl;

输出:

a 不等于 3.2
b 等于 3.2f

在 ideone 做实验:http ://www.ideone.com/pAGzM

尝试将变量的类型a从更改floatdouble,再次查看结果

于 2011-04-06T06:56:57.290 回答
5

常见问题解答

[29.16] 为什么浮点数如此不准确?为什么这不打印 0.43?

#include <iostream>

 int main()
 {
   float a = 1000.43;
   float b = 1000.0;
   std::cout << a - b << '\n';
   ...
 }

免责声明:舍入/截断/近似的挫败感并不是真正的 C++ 问题;这是一个计算机科学问题。然而,人们一直在 comp.lang.c++ 上询问它,所以下面是一个名义上的答案。

:浮点数是近似值。32 位浮点数的 IEEE 标准支持 1 位符号、8 位指数和 23 位尾数。由于归一化二进制点尾数始终具有 1.xxxxx 的形式......前导 1 被丢弃,您实际上得到了 24 位尾数。数字 1000.43(以及许多其他数字,包括一些非常常见的数字,例如 0.1)不能完全以浮点或双精度格式表示。1000.43实际上表示为以下位模式(“s”表示符号位的位置,“e”表示指数位的位置,“m”表示尾数位的位置):

 seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm
 01000100011110100001101110000101

移位后的尾数为 1111101000.01101110000101 或 1000 + 7045/16384。小数部分是 0.429992675781。使用 24 位尾数,您只能获得大约 16M 精度的浮点数。double 类型提供更高的精度(53 位尾数)。

另外,请参阅[29.17] 为什么我的浮点比较不起作用?

于 2011-04-06T06:58:34.813 回答
2

ceil(x)函数返回不小于 then 的最小整数x

由于您键入的常量(如4.11or 1.21)没有精确表示 - 它们可能碰巧用稍小的数字或稍大的数字表示,或者在极少数情况下用相等的数字表示。例如,您的编译器将常量表示4.11为稍大的数字,因此4.11*100恰好比 411 略大ceil(4.11*100) == 412(因为 412 是不小于略大于 411 的数字的最小数字),但1.21表示为略小的数字,因此1.21*100略小于 121所以ceil(1.21*100)==121

另请注意,乘法也不精确。

于 2011-04-06T07:24:21.477 回答