C ++浮点精度

可能重复:
浮点不准确的例子

double a = 0.3; std::cout.precision(20); std::cout << a << std::endl; 

结果:0.2999999999999999889

 double a, b; a = 0.3; b = 0; for (char i = 1; i <= 50; i++) { b = b + a; }; std::cout.precision(20); std::cout << b << std::endl; 

结果:15.000000000000014211

所以..’a’比它应该小。 但是,如果我们采取’a’50次 – 结果会比它应该更大。

为什么是这样? 如何在这种情况下得到正确的结果?

要获得正确的结果,请不要将精度设置为大于此数值类型的可用精度:

 #include  #include  int main() { double a = 0.3; std::cout.precision(std::numeric_limits::digits10); std::cout << a << std::endl; double b = 0; for (char i = 1; i <= 50; i++) { b = b + a; }; std::cout.precision(std::numeric_limits::digits10); std::cout << b << std::endl; } 

虽然如果该循环运行5000次迭代而不是50次,即使使用这种方法,累积的错误也会出现 - 它只是浮点数的工作原理。

为什么是这样?

因为浮点数以二进制forms存储,其中0.3是0.01001100110011001 …重复就像1/3是0.333333 …重复十进制。 当你写0.3 ,你实际上得到0.299999999999999988897769753748434595763683319091796875(无限二进制表示舍入到53位有效数字)。

请记住,对于设计浮点的应用程序,不能完全代表0.3的问题。 浮点设计用于:

  • 物理测量,通常只测量4 sig figs, 从不测量超过15。
  • 超越函数,如对数和三角函数,无论如何都是近似的。

对于哪些二进制十进制转换与其他错误源相比几乎无关紧要。

现在,如果您正在编写财务软件,其中0.30美元的价格恰好是 0.30美元,那就不同了。 有针对这种情况设计的十进制算术类。

如何在这种情况下得到正确的结果?

将精度限制为15位有效数字通常足以隐藏“噪音”数字。 除非您确实需要一个确切的答案,否则这通常是最好的方法。

计算机以二进制forms存储浮点数,而非十进制数。

许多看起来很普通的数字,例如0.3,没有二进制有限长度的精确表示。
因此,编译器选择具有精确二进制表示的最接近的数字,就像为1⁄3编写0.33333一样。

如果添加许多浮点数,这些微小的差异会加起来,并且会得到意想不到的结果。

并不是它更大或更小,只是在物理上不可能将“0.3”存储为二进制浮点数内的精确值。

获得“正确”结果的方法是不显示20个小数位。

要获得“正确”的结果,请尝试

维基百科中的任意精度算术库列表: http : //en.wikipedia.org/wiki/Arbitrary-precision

要么

http://speleotrove.com/decimal