我有点C新手,但这个问题让我很困惑。
我有一个变量double = 436553940.0000000000(它是从Int转换而来)和另一个变量double 0.095832496。
我的结果应该是436553940.0958324 * 96 *,但是我得到436553940.0958324 * 67 *。
为什么会发生这种情况?如何防止它发生?
答案 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标准(和您的编译器)定义了一些规则,告诉我们如何舍入数字,以达到最接近的可表示的双倍。