C++ 浮点精度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2909427/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ floating point precision
提问by Davinel
Possible Duplicate:
Floating point inaccuracy examples
可能的重复:
浮点不准确示例
double a = 0.3;
std::cout.precision(20);
std::cout << a << std::endl;
result: 0.2999999999999999889
结果: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;
result: 15.000000000000014211
结果:15.000000000000014211
So.. 'a' is smaller than it should be. But if we take 'a' 50 times - result will be bigger than it should be.
所以.. 'a' 比它应该的要小。但是如果我们取 'a' 50 次 - 结果会比它应该的大。
Why is this? And how to get correct result in this case?
为什么是这样?在这种情况下如何获得正确的结果?
回答by Cubbi
To get the correct results, don't set precision greater than available for this numeric type:
要获得正确的结果,请不要将精度设置为大于此数字类型的可用精度:
#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;
}
Although if that loop runs for 5000 iterations instead of 50, the accumulated error will show up even with this approach -- it's just how floating-point numbers work.
尽管如果该循环运行 5000 次迭代而不是 50 次,即使使用这种方法,累积的错误也会出现——这就是浮点数的工作原理。
回答by dan04
Why is this?
为什么是这样?
Because floating-point numbers are stored in binary, in which 0.3 is 0.01001100110011001... repeating just like 1/3 is 0.333333... is repeating in decimal. When you write 0.3
, you actually get 0.299999999999999988897769753748434595763683319091796875 (the infinite binary representation rounded to 53 significant digits).
因为浮点数是以二进制形式存储的,其中 0.3 是 0.01001100110011001...重复就像 1/3 是 0.333333...以十进制重复。当你写时0.3
,你实际上得到 0.299999999999999988897769753748434595763683319091796875(无限二进制表示四舍五入到 53 个有效数字)。
Keep in mind that for the applications for which floating-point is designed, it's not a problem that you can't represent 0.3 exactly. Floating-point was designed to be used with:
请记住,对于为浮点设计的应用程序,不能精确表示 0.3 不是问题。浮点设计用于:
- Physical measurements, which are often measured to only 4 sig figs and neverto more than 15.
- Transcendental functions like logarithms and the trig functions, which are only approximated anyway.
- 物理测量,通常测量到只有 4 个无花果,从不超过 15 个。
- 超越函数,如对数和三角函数,无论如何都只是近似的。
For which binary-decimal conversions are pretty much irrelevant compared to other sources of error.
与其他错误来源相比,哪些二进制-十进制转换几乎无关紧要。
Now, if you're writing financial software, for which $0.30 means exactly$0.30, it's different. There are decimal arithmetic classes designed for this situation.
现在,如果你正在写的财务软件,其中$ 0.30手段究竟$ 0.30,这是不同的。有针对这种情况设计的十进制算术类。
And how to get correct result in this case?
在这种情况下如何获得正确的结果?
Limiting the precision to 15 significant digits is usually enough to hide the "noise" digits. Unless you actually needan exact answer, this is usually the best approach.
将精度限制为 15 个有效数字通常足以隐藏“噪声”数字。除非您确实需要确切的答案,否则这通常是最好的方法。
回答by SLaks
Computers store floating point numbers in binary, not decimal.
计算机以二进制而不是十进制存储浮点数。
Many numbers that look ordinary in decimal, such as 0.3, have no exact representation of finite length in binary.
Therefore, the compiler picks the closest number that has an exact binary representation, just like you write 0.33333
for 1?3
.
许多在十进制中看起来很普通的数字,例如 0.3,在二进制中没有精确的有限长度表示。
因此,编译器会选择具有精确二进制表示的最接近的数字,就像您为 编写0.33333
的那样1?3
。
If you add many floating-point numbers, these tiny difference add up, and you get unexpected results.
如果你添加许多浮点数,这些微小的差异加起来,你会得到意想不到的结果。
回答by Dean Harding
It's not that it's bigger or smaller, it's just that it's physically impossible to store "0.3" as an exact value inside a binary floating point number.
并不是它更大或更小,只是物理上不可能将“0.3”存储为二进制浮点数中的精确值。
The way to get the "correct" result is to not display 20 decimal places.
获得“正确”结果的方法是不显示 20 位小数。
回答by Larry K
To get the "correct" result, try
要获得“正确”的结果,请尝试
List of Arbitrary-precision arithmetic Libraries from Wikipedia: http://en.wikipedia.org/wiki/Arbitrary-precision
来自维基百科的任意精度算术库列表:http: //en.wikipedia.org/wiki/Arbitrary-precision
or
或者