简体   繁体   English

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

[英]Why there is no errors while multiplying floating point numbers?

I need some clearification about floating point math. 我需要对浮点数学进行一些澄清。

I have wrote some code for the learning purpouses: 我为学习者写了一些代码:

#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;
}

and the output it gives is: 它给出的输出是:

    1
    1
    0.99999999999999989
    0

Why (sum == 1.0) - is false is pretty understandabale, but why multiplying gives the right answer without the error? 为什么(sum == 1.0) - 是假的是相当可理解的,但为什么乘法给出正确答案而没有错误?

Thanks. 谢谢。

If you look at the actual assembly language produced, you'll find that the compiler is not generating the single multiplication you're asking for. 如果查看生成的实际汇编语言,您会发现编译器没有生成您要求的单个乘法。 Instead, it's simply providing the actual value. 相反,它只是提供实际价值。 If you turn off optimization you might get the results you're expecting (unless your compiler optimizes this anyway). 如果关闭优化,您可能会得到您期望的结果(除非您的编译器无论如何都要优化它)。

When performing the repeated addition, there are 9 roundings taking place: the first result a+a is always exactly representable, but after that, further additions are inexact since the base-2 exponents of the addends are not equal. 当执行重复加法时,发生了9次舍入:第一个结果a+a总是可以精确表示,但之后,由于加数的基数2指数不相等,所以进一步加法是不精确的。

When performing the multiplication, there's only a single rounding, and it happens to give you the result you wanted. 执行乘法时,只有一个舍入,它恰好会给你想要的结果。

There are a lot of problems with your code. 您的代码存在很多问题。

floating point on a computer is base 2. You cannot represent 0.1 exactly in floating point (just like you cant represent 1/3rd in base 10 compared apples to apples), so any other assumptions after that (multiply by 10 and expect it to be a one for example) are bad. 计算机上的浮点数是基数2.你不能完全用浮点表示0.1(就像你不能代表基数10的1/3比较苹果到苹果),所以之后的任何其他假设(乘以10并期望它是例如一个人是坏的。

The single multiply of 10 times 0.1 only incurs one times the error. 单次乘以10倍0.1只会产生误差的一倍。 The multiple additions incur 10 times the error. 多次添加会产生10倍的误差。 Rounding fixes the 10 times 0.1 when converting to integer making it look like it actually worked. 当转换为整数时,舍入修复了10倍0.1,使其看起来像实际工作。 Rounding being yet another feature of IEEE floating point, the rounding mode used by default on your system as well as whatever the 1/10th became again basically made the single multiply look like it worked. 舍入是IEEE浮点的另一个特性,默认情况下在您的系统上使用的舍入模式以及1/10变为基本上使得单个乘法看起来像它起作用。

next problem is you are doing equals comparisons with floating point and I assume having some sort of expectation. 下一个问题是你正在做与浮点相等的比较,我假设有某种期望。 dont use equals on float, period. 不要在浮动,期间使用等于。 Certainly not with numbers like this that cannot be represented exactly in floating point. 当然不是这样的数字不能用浮点表示。

try a number like 1/16th for example or 1/8th instead of 1/10th... 尝试像1/16或1/8而不是1/10的数字...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM