1

可能的重复:
JavaScript 的数学被破坏了吗?
处理浮点数的精度问题

考虑下面的代码及其输出:

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cmath>
#include <limits>
#include <vector>


int main(int argc, char *argv[])
{
  double xleft  = 0;
  double xright = 1.0;

  double dx = 0.1;
  std::cout << std::setprecision(36) << "dx is " << dx << std::endl; 

  int numgridpts = ((int) ceil (( xright - xleft )/dx))  + 1; 


  for (int i = 0; i < numgridpts  ; ++i)
    {
      std::cout << std::setprecision(36) << xleft + i*dx << std::endl;
    }

  return 0;
}

[~:ICgen/$ ./a.out                                                                                                                               
dx is 0.100000000000000005551115123125782702
0
0.100000000000000005551115123125782702
0.200000000000000011102230246251565404
0.300000000000000044408920985006261617
0.400000000000000022204460492503130808
0.5
0.600000000000000088817841970012523234
0.700000000000000066613381477509392425
0.800000000000000044408920985006261617
0.900000000000000022204460492503130808
1

我的问题是,当我将数字打印到 36 位精度时,为什么数字 0 、 0.5 和 1.0 精确表示,而其他数字似乎在末尾放置了一些垃圾数字?

此外,如果我添加 0.2 和 0.1 的浮点表示,如上面的输出所示,它们似乎与 0.3 的表示相加,在垃圾位的部分。

我正在使用 Linux Ubuntu 10.10 和 gcc 编译器

4

1 回答 1

5

这些不是垃圾数字,而是根据 IEEE 754 标准在浮点表示中尽可能准确的数字值。

该标准使用二进制数,而不是十进制数。因此,像 1/2、1/4、1/8(= 0.5、0.25、0.125、...)这样的分数和它们的倍数可以精确表示,而像 1/3 或 1/10 这样的分数则不是。

如果这是一个十进制数字系统,那么像 1/10、1/100、1/1000... 这样的分数以及它们的倍数将是唯一用有限位数精确表示的数字。

在这两个系统中,如果它们不是非常大,所有整数都被精确表示。

于 2012-04-04T21:02:42.293 回答