我在第174页,C-Al Kelley,Ira Pohl的书上找到了这段代码。
int main()
{
int cnt=0; double sum=0.0,x;
for( x=0.0 ;x!= 9.9 ;x+=0.1)
{
sum=sum +x;
printf("cnt = %5d\n",cnt++);
}
return 0;
}
并且它成了一个无限循环,正如书中所说的那样。它没有提到确切的原因,只是说它与机器的准确性有关。
我修改了代码以检查是否 X = 9.9 将永远变为现实,即通过添加以下行来获得9.9
diff=x-9.9;
printf("cnt =10%d \a x =%10.10lf dif=%10.10lf \n",++cnt,x,diff);
我在输出中得到以下几行
cnt =1098 x =9.7000000000 dif=-0.2000000000
cnt =1099 x =9.8000000000 dif=-0.1000000000
cnt =10100 x =9.9000000000 dif=-0.0000000000
cnt =10101 x =10.0000000000 dif=0.1000000000
cnt =10102 x =10.1000000000 dif=0.2000000000
如果x正好达到9.9的值,为什么它仍然是无限循环?
答案 0 :(得分:1)
问题是大多数浮点实现都基于IEEE 754.请参阅http://en.wikipedia.org/wiki/IEEE_floating_point
问题在于,数字是用基数2(二进制格式)构建的。
数字9.9永远不能用基数2来构建。
David Goldberg撰写的“数值计算指南”对此有一个确切的陈述:
已经提出了几种不同的实数表示, 但到目前为止,使用最广泛的是浮点表示法。 浮点表示有一个基数b(总是假设为 是偶数)和精度p。如果b = 10且p = 3,那么数字0.1是 表示为1.00×10 ^ -1。如果b = 2且p = 24,则为小数 数字0.1不能精确表示,但大约是 1.10011001100110011001101×2 ^ -4。
答案 1 :(得分:1)
您只是打印数字的准确性太差,不会发现它不准确。尝试这样的事情:
#include <stdio.h>
int main()
{
double d = 9.9;
if(d == 9.9)
{
printf("Equal!");
}
else
{
printf("Not equal! %.20f", d);
}
}
我机器上的输出:
Not equal! 9.90000000000000035527
本书可能会试图教你永远不要使用==或!=运算符来比较浮点变量。同样出于同样的原因,永远不要使用浮点数作为循环迭代器。
答案 2 :(得分:0)
您可以放心地假设两个浮点数从不等于'完全'(除非一个是另一个的副本)。
答案 3 :(得分:0)
计算机适用于二进制和浮点,换句话说就是基数2.就像基数10一样,基数2具有无法构建的数字。例如,尝试在基数10中写出分数10/3。最终会得到无限的3。在Binary中,你甚至不能用二进制写0.1(十进制),你也会得到一个循环模式0.0001100110011 ......(二进制)。