为什么浮点数乘以时没有错误?

时间:2014-02-09 01:34:26

标签: c floating-point

我需要对浮点数学进行一些澄清。

我为学习者写了一些代码:

#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) - 是错误的是相当可理解的,但为什么乘法给出正确答案而没有错误?

感谢。

3 个答案:

答案 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 ...