g ++和双精度

时间:2020-05-06 14:36:53

标签: c++

任何人都可以向我解释为什么执行以下代码会返回(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

平等!

1 个答案:

答案 0 :(得分:3)

假设您的double类型符合IEEE 754,则1.0 / 3.0的十六进制表示形式为3FD5555555555555。这不完全是1/3。它分解为:

  • 符号= 0(即数字为正)
  • 偏置指数= 3FD(即指数= -2)
  • 53位尾数= 15555555555555(暗指前导1

15555555555555乘以3得到3FFFFFFFFFFFFF。要将其压缩为53位,我们必须舍弃最低有效位(在大多数环境中,默认舍入模式下)是将尾数“舍入为偶数”:尾随二进制01移至{{1 }},尾随的二进制0到达11(这意味着可能传播进位)。在这种情况下,进位一直传播到最高有效位,100留在尾数中。我们希望位52是最高有效位,因此我们将其下移到40000000000000并将指数增加2。最终结果是10000000000000,或者恰好是1.0。

因此您的程序行为正确-不精确的结果乘以一个小整数将为您提供准确的结果。但是人们可以认为,运气比判断还好:-)