Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么浮点数相乘时没有错误?_C_Floating Point - Fatal编程技术网

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

C 为什么浮点数相乘时没有错误?,c,floating-point,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

我需要一些关于浮点数学的知识

我已经为学习目的编写了一些代码:

#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;
}
为什么(sum==1.0)-为false是很容易理解的,但是为什么乘法给出了正确的答案而没有错误呢


谢谢。

如果您查看实际生成的汇编语言,您会发现编译器没有生成您要求的单个乘法。相反,它只是提供实际的价值。如果关闭优化,您可能会得到预期的结果(除非您的编译器对此进行了优化)。

执行重复加法时,会发生9次取整:第一个结果
a+a
始终是完全可表示的,但之后,进一步的加法是不精确的,因为加法的基2指数不相等


当执行乘法时,只有一个舍入,它恰好给出了您想要的结果。

您的代码有很多问题

计算机上的浮点是基数2。你不能用浮点来精确地表示0.1(就像你不能用10进制来表示1/3的苹果数),所以在那之后的任何其他假设(比如乘以10,期望它是1)都是不好的

10乘以0.1只会产生一倍的误差。多次添加会导致10倍的错误。舍入修正了转换为整数时的10倍0.1,使其看起来像实际工作。舍入是IEEE浮点的另一个特性,系统默认使用的舍入模式以及1/10的值基本上使单乘法看起来可以工作

下一个问题是,您正在使用浮点进行相等比较,我假设您有某种期望。不要在浮点数上使用等号,句号。当然不是像这样的数字,不能用浮点精确表示


例如,尝试使用1/16或1/8而不是1/10这样的数字…

这将是一个不正确的优化,因此编译器不应该在不符合标准的配置文件中进行优化…实际上,
a+a+a
也总是,除非溢出,确切地说是
4*a
(这是Stephen Canon提供的小贴士)@PascalCuoq:不,不是<代码>(a+a)+(a+a)正好是
4*a
。但浮点加法不是关联的。在默认舍入模式(最接近/与偶数成正比)下,通过一个关于发生舍入的参数,该声明可能是正确的,但在一般情况下肯定不是正确的。该注释显然是在IEEE 754指定的二进制格式的上下文中,舍入到最接近的偶数。如果你要分心,你的解释假设一个二进制格式,这在问题中没有任何理由。IEEE 754有多种舍入模式,并指定了所有模式的行为,因此我反对假设默认模式在这种情况下是有意义的。至少应该注意的是,行为取决于舍入模式,因为否则声明看起来显然是错误的。Re,它恰好给了您想要的结果——这是关键。在我的计算机上,使用默认舍入,有许多数字(1.0/x)*x不等于1.0。(例如,x=49.0)。最好将浮点数视为实数的粗略近似值。即使是能够进行无限精度运算的理想图灵机,也会遇到实数的问题,因为几乎所有的实数都不是可计算的数字。
    1
    1
    0.99999999999999989
    0