C / C ++程序中数字的浮点表示中的垃圾比特

时间:2012-04-04 20:57:35

标签: c++ floating-point floating-accuracy

  

可能重复:
  Is JavaScript's Math broken?
  Dealing with accuracy problems in floating-point numbers

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

#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编译器

1 个答案:

答案 0 :(得分: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 ......及其倍数将是唯一用有限位数表示的数字。

在两个系统中,如果它们不是非常大,则表示所有整数。