任何人都可以向我解释为什么执行以下代码会返回(1 / .3)* 3。等于1。我以为四舍五入会阻止这样的平等,但显然那样行不通。有什么解释吗?
#include <iostream>
int main()
{
double x = 1./3.;
double y = 3.*x;
std::cout.precision(30);
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
if (y == 1.)
std::cout << "Equality!" << std::endl;
else
std::cout << "Not equality." << std::endl;
return 0;
}
它返回:
$ g ++ test_dp.cpp -o test_dp.exe
$ ./test_dp.exe
x = 0.333333333333333314829616256247
y = 1
平等!
答案 0 :(得分:3)
假设您的double
类型符合IEEE 754,则1.0 / 3.0的十六进制表示形式为3FD5555555555555
。这不完全是1/3。它分解为:
3FD
(即指数= -2)15555555555555
(暗指前导1
)将15555555555555
乘以3得到3FFFFFFFFFFFFF
。要将其压缩为53位,我们必须舍弃最低有效位(在大多数环境中,默认舍入模式下)是将尾数“舍入为偶数”:尾随二进制01
移至{{1 }},尾随的二进制0
到达11
(这意味着可能传播进位)。在这种情况下,进位一直传播到最高有效位,100
留在尾数中。我们希望位52是最高有效位,因此我们将其下移到40000000000000
并将指数增加2。最终结果是10000000000000
,或者恰好是1.0。
因此您的程序行为正确-不精确的结果乘以一个小整数将为您提供准确的结果。但是人们可以认为,运气比判断还好:-)