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次 - 结果会比它应该更大。
这是为什么? 如何在这种情况下得到正确的结果?
答案 0 :(得分:16)
要获得正确的结果,请不要将精度设置为大于此数值类型的可用精度:
#include <iostream>
#include <limits>
int main()
{
double a = 0.3;
std::cout.precision(std::numeric_limits<double>::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<double>::digits10);
std::cout << b << std::endl;
}
虽然如果该循环运行5000次迭代而不是50次,即使使用这种方法,累积的错误也会出现 - 它只是浮点数的工作原理。
答案 1 :(得分:10)
为什么会这样?
因为浮点数以二进制形式存储,其中0.3是0.01001100110011001 ...重复就像1/3是0.333333 ...重复十进制。当你写0.3
时,实际得到0.299999999999999988897769753748434595763683319091796875(无限二进制表示四舍五入为53位有效数字)。
请记住,对于设计浮点的应用程序,不能完全代表0.3的问题。浮点设计用于:
与其他错误源相比,二进制十进制转换几乎无关紧要。
现在,如果您正在编写财务软件,其中0.30美元意味着完全 0.30美元,那就不同了。有针对这种情况设计的十进制算术类。
如何在这种情况下获得正确的结果?
将精度限制为15位有效数字通常足以隐藏“噪音”数字。除非你实际上需要一个确切的答案,否则这通常是最好的方法。
答案 2 :(得分:7)
计算机以二进制形式存储浮点数,而不是十进制数。
许多看起来很普通的数字,例如0.3,没有二进制有限长度的精确表示
因此,编译器会选择具有精确二进制表示的最接近的数字,就像为0.33333
编写1⁄3
一样。
如果添加许多浮点数,这些微小的差异会累加起来,并且会得到意想不到的结果。
答案 3 :(得分:1)
不是它更大或更小,只是在物理上不可能将“0.3”存储为二进制浮点数内的精确值。
获得“正确”结果的方法是不显示20位小数。
答案 4 :(得分:-2)