c++天花板函数的奇怪结果

Strange results with C++ ceiling function

本文关键字:结果 天花板 函数 c++      更新时间:2023-10-16

我一直在尝试天花板函数,并得到一些奇怪的结果。如果我对一个十进制数乘以100进行顶数运算,就会得到一个确定的结果。但是,如果我直接对乘法的结果执行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.11没有被表示成4.11,而是非常接近于它。当这个"非常接近4.11"的数字乘以100时,产物的ceil变成了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的类型从float更改为double,再次查看结果

来自FAQ:

[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++,所以后面是a名义回答。

答案:浮点数是an近似。IEEE标准32位浮点数支持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位,你只能得到1个部分浮子精度为16M。双Type提供更高的精度(53位)尾数)。

同样,参见[29.17]为什么我的浮点比较不起作用?

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

由于您键入的常量(如4.111.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

还要注意乘法也不是精确的