C 平等性检验与机器精度
我在第174页找到了这个代码片段,这是一本关于艾拉·波尔的C-Al Kelley的书C 平等性检验与机器精度,c,C,我在第174页找到了这个代码片段,这是一本关于艾拉·波尔的C-Al Kelley的书 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 将成为现实,即通
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
将成为现实,即通过添加以下行,x达到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的值,为什么它仍然是一个无限循环?您可以放心地假设两个浮点数永远不会“完全”相等(除非一个是另一个的副本)。问题是大多数浮点数实现都基于IEEE 754。看 问题是,数字是用基数2(二进制格式)构建的 数字9.9绝对不能用基2构建 David Goldberg GV的“数值计算指南”对此作了准确的说明: 提出了几种不同的实数表示法, 但到目前为止,最广泛使用的是浮点表示法。 浮点表示法有一个基数b(通常假定为 是均匀的)和一个精确的p。如果b=10,p=3,则数字0.1为 表示为1.00×10^-1。如果b=2,p=24,则小数点 数字0.1无法精确表示,但近似为 1.10011001×2^-4
你只是简单地以太低的精度打印数字,以至于没有注意到它不准确。试着这样做:
#include <stdio.h>
int main()
{
double d = 9.9;
if(d == 9.9)
{
printf("Equal!");
}
else
{
printf("Not equal! %.20f", d);
}
}
这本书可能是想教你永远不要使用==或!=运算符来比较浮点变量。同样出于同样的原因,千万不要将浮点用作循环迭代器。计算机使用二进制和浮点运算,换句话说,使用基数2。就像基数10一样,基数2也有它无法构建的数字。例如,试着把分数10/3写在基数10中。你将得到无限的3。在二进制中,你甚至不能用二进制写0.1(十进制),你还会得到一个循环模式0.000110011。。。(二进制)
本视频将更好地解释从哪里来的
X
。。。???你是说sum!=9.9
循环条件下的。这是许多类似问题的重复。底线-双精度不能准确地表示0.1
,因此您将得到99*0.1!=9.9
。
Not equal! 9.90000000000000035527