添加两个双精度会在C中产生奇怪的舍入结果

时间:2014-04-13 16:33:17

标签: c double

我有点C新手,但这个问题让我很困惑。

我有一个变量double = 436553940.0000000000(它是从Int转换而来)和另一个变量double 0.095832496。

我的结果应该是436553940.0958324 * 96 *,但是我得到436553940.0958324 * 67 *。

为什么会发生这种情况?如何防止它发生?

2 个答案:

答案 0 :(得分:0)

您期望的数字无法由double表示。您收到的值是基于舍入结果的近似值:

In [9]: 436553940.095832496
Out[9]: 436553940.09583247

In [18]: 436553940.095832496+2e-8
Out[18]: 436553940.09583247

In [19]: 436553940.095832496+3e-8
Out[19]: 436553940.0958325

In [20]: 436553940.095832496-2e-8
Out[20]: 436553940.09583247

In [21]: 436553940.095832496-3e-8
Out[21]: 436553940.0958324

你刚用完了有效位。

答案 1 :(得分:0)

双打不能代表每个数字。我们可以编写一些C ++代码(以相同的方式实现双精度)来显示它。

#include <cstdio>
#include <cmath>

int main() {
    double x = 436553940;
    double y = 0.095832496;

    double sum = x + y;

    printf("prev: %50.50lf\n", std::nextafter(sum, 0));
    printf("sum:  %50.50lf\n", sum);
    printf("next: %50.50lf\n", std::nextafter(sum, 500000000));
}

此代码计算您正在谈论的两个数字的总和,并将其存储为sum。然后,我们计算该数字之前的下一个可表示的双精度数,并在该数字之后计算。

这是输出:

[11:43am][wlynch@watermelon /tmp] ./foo
prev: 436553940.09583240747451782226562500000000000000000000000000
sum:  436553940.09583246707916259765625000000000000000000000000000
next: 436553940.09583252668380737304687500000000000000000000000000

因此,我们无法使计算等于436553940.0958324_96_,因为该数字不是有效的双精度数。因此,IEEE-754标准(和您的编译器)定义了一些规则,告诉我们如何舍入数字,以达到最接近的可表示的双倍。