C++浮点精度

发布于 2024-09-02 18:48:36 字数 601 浏览 2 评论 0原文

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

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 次 - 结果将比应有的大。

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

Possible Duplicate:
Floating point inaccuracy examples

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

result: 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

So.. 'a' is smaller than it should be.
But if we take 'a' 50 times - result will be bigger than it should be.

Why is this?
And how to get correct result in this case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

樱花细雨 2024-09-09 18:48:36

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

#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 次,即使使用此方法,累积误差也会显示出来 - 这就是浮点数的情况工作。

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.

久随 2024-09-09 18:48:36

这是为什么?

因为浮点数是以二进制存储的,其中0.3是0.01001100110011001...重复就像1/3是0.333333...在十进制中重复。当您编写 0.3 时,您实际上得到 0.299999999999999988897769753748434595763683319091796875 (无限二进制表示形式四舍五入到 53 位有效数字)。

请记住,对于设计浮点的应用程序,不能精确表示 0.3 并不是问题。浮点设计用于:

  • 物理测量,通常仅测量到 4 个数字,永远 不会超过 15 个。
  • 超越函数,如对数和三角函数,无论如何都只能近似。

与其他错误源相比,二进制到十进制转换几乎无关紧要。

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

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

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

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).

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:

  • Physical measurements, which are often measured to only 4 sig figs and never to more than 15.
  • Transcendental functions like logarithms and the trig functions, which are only approximated anyway.

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.

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 need an exact answer, this is usually the best approach.

新人笑 2024-09-09 18:48:36

计算机以二进制而不是十进制存储浮点数。

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

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

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.

If you add many floating-point numbers, these tiny difference add up, and you get unexpected results.

过潦 2024-09-09 18:48:36

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

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

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.

The way to get the "correct" result is to not display 20 decimal places.

半衬遮猫 2024-09-09 18:48:36

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

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

http://speleotrove.com/decimal

To get the "correct" result, try

List of Arbitrary-precision arithmetic Libraries from Wikipedia:
http://en.wikipedia.org/wiki/Arbitrary-precision

or

http://speleotrove.com/decimal

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文