我们可以假设任何一对跟随浮点算术语句总是产生相同的结果吗?

时间:2014-07-24 20:25:53

标签: c++ c floating-point floating-point-precision

给出以下任意值的浮点变量,用c / c ++。

float a, b, c, d;

在以下陈述中,我们可以假设它们中的任何一对总是会产生相同的结果吗?

float result_1 = a + b + c + d - c;
float result_2= a + b + c + (d - c);
float result_3 = a + b + d;

此外,对后续谓词是否有任何保证:

a + b - b == a

3 个答案:

答案 0 :(得分:4)

不,你不能假设这一点。我打破了你的所有三个例子:(Live)

#include <iostream>

int main()
{
   double a = 1, b = 1e100, c= 1e100, d= 1, c2 = .1, d2 = -.1, b2 = 1;

   std::cout << ( a + b2 + c2 + d2 - c2 == a + b2 + c2 + (d2 - c2)) << "\n"
    << ( a + b2 + c + d - c == a + b2 + d) << "\n"
    << ( a == a + b -b);
}

输出:

  

0   0   0

==!=在浮点类型上始终不安全,因为它有舍入错误。

答案 1 :(得分:0)

首先,我们在计算机上说明关于浮点数的标准警告。它们本质上是不精确的。没有办法在二进制文件中准确地说".1"。所以,任何一个可能会给你一个错误的&#34;回答。但是,一般来说,他们应该给你同样错误的答案。

一般来说,乘法和除法的变化多于加法和减法。并且,在同一计算中处理非常大的数字和非常小的数字时,你会遇到麻烦。

[更新]下一句话错了。忽略它:
但是,据我所知,在这个极限情境中,似乎一切都正确平衡,所以虽然我不能断然说出来,但我认为你在这里安全。

答案 2 :(得分:0)

如果我运行以下代码:

#include <stdio.h>

int main(int argc, char* argv[])
{
    float a = 0.1;
    float b = 0.2;
    float c = 0.3;
    float d = 0.4;

    float result1 = a + b + c + d - c;
    float result2 = a + b + c + (d - c);
    float result3 = a + b + d;

    printf("result1 == result2: %s\n", result1 == result2 ? "Yes" : "No");
    printf("result2 == result3: %s\n", result2 == result3 ? "Yes" : "No");
    printf("result1 == result3: %s\n\n", result1 == result3 ? "Yes" : "No");

    printf("result1: %30.20f\n", result1);
    printf("result2: %30.20f\n", result2);
    printf("result3: %30.20f\n\n", result3);

    printf("a + b:               %30.20f\n", a + b);
    printf("a + b + c:           %30.20f\n", a + b + c);
    printf("a + b + c + d:       %30.20f\n", a + b + c + d);
    printf("d - c:               %30.20f\n", d - c);
    printf("a + b + c + d - c:   %30.20f\n", a + b + c + d - c);
    printf("a + b + c + (d - c): %30.20f\n", a + b + c + (d - c));
    printf("a + b + d:           %30.20f\n", a + b + d);

    return 0;
}

我得到以下输出,显示主要问题的答案是

result1 == result2: No
result2 == result3: Yes
result1 == result3: No

result1:         0.69999998807907104492
result2:         0.70000004768371582031
result3:         0.70000004768371582031

a + b:                       0.30000001192092895508
a + b + c:                   0.60000002384185791016
a + b + c + d:               1.00000000000000000000
d - c:                       0.09999999403953552246
a + b + c + d - c:           0.69999998807907104492
a + b + c + (d - c):         0.70000004768371582031
a + b + d:                   0.70000004768371582031

编译器:Apple LLVM 5.1(clang)。

我得到了相同的结果,但没有使用我试过的另一个编译器。最后一个使用32位代码的x86 FPU。另外两个以64位模式运行并使用SSE2,AFAIK。