我需要对浮点数学进行一些澄清。
我为学习者写了一些代码:
#include "stdio.h"
int main (int argc, char const *argv[])
{
int i;
double a=1.0/10.0;
double sum=0;
for(i = 0; i < 10; ++i)
sum+=a;
printf("%.17G\n", 10*a );
printf("%d\n", (10*a == 1.0) );
printf("%.17G\n", sum );
printf("%d\n", (sum == 1.0) );
return 0;
}
,它给出的输出是:
1
1
0.99999999999999989
0
为什么(sum == 1.0) - 是错误的是相当可理解的,但为什么乘法给出正确答案而没有错误?
感谢。
答案 0 :(得分:2)
如果查看生成的实际汇编语言,您会发现编译器没有生成您要求的单个乘法。相反,它只是提供实际价值。如果你关闭优化,你可能会得到你期望的结果(除非你的编译器无论如何都要优化它)。
答案 1 :(得分:1)
执行重复添加时,会发生9次舍入:第一个结果a+a
始终可以准确表示,但在此之后,由于加数的基数2指数不相等,因此进一步添加是不精确的。
执行乘法时,只有一个舍入,它恰好可以得到你想要的结果。
答案 2 :(得分:0)
您的代码存在很多问题。
计算机上的浮点数是基数2.你不能完全代表浮点数0.1(就像你不能代表基数10中的1/3比较苹果到苹果),所以之后的任何其他假设(乘以10并期望它是一个例如)是坏的。
单次乘以10倍0.1只会产生误差的一倍。多次添加会产生10倍的误差。当转换为整数时,舍入修复了10倍0.1,使其看起来像实际工作。舍入是IEEE浮点的另一个特性,默认情况下在您的系统上使用的舍入模式以及任何1/10的舍入模式基本上都使得单个乘法看起来像它起作用。
接下来的问题是你正在做与浮点数相等的比较,我假设有某种期望。不要在浮动,期间使用等于。当然不是这样的数字不能用浮点表示。
尝试一个数字,例如1/16或1/8而不是1/10 ...