Python 的舍入问题

发布于 2024-12-06 11:23:22 字数 502 浏览 2 评论 0原文

可能的重复:
Python 浮点数舍入错误

我在 Python 中遇到舍入问题。如果我计算

32.50 * 0.19 = 6.1749999999999998

但这应该是 6.175。如果我将 6.1749999999999998 四舍五入到小数点后两位,它会正确显示 6.18。所以我可以忍受。

但如果我计算一下:

32.50 * 0.19 * 3 = 18.524999999999999

这应该是 18.525。如果我将值 18.524999999999999 四舍五入到小数点后两位,则显示为 18.52。

它应该显示 18.53。我做错了什么以及如何解决它?

Possible Duplicate:
Python rounding error with float numbers

I have a rounding Problem in Python. If i calculate

32.50 * 0.19 = 6.1749999999999998

But this should be 6.175. If i round 6.1749999999999998 with 2 decimal places it correctly shows 6.18. So i can live with that.

But if i calculate this:

32.50 * 0.19 * 3 = 18.524999999999999

This should be 18.525. If i round the value 18.524999999999999 with two decimal places it shows 18.52.

It should show me 18.53. What am i doing wrong and how can i fix it ?

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

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

发布评论

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

评论(7

旧时浪漫 2024-12-13 11:23:22

每个计算机科学家应该了解的浮点运算知识。

简而言之 - 您不应该依赖浮点数的精确值,因为它们在内存中的存储方式。

另请参阅有关它的 python 文档 - 浮点算术:问题和限制。它包含下一段:

例如,如果您尝试将值 2.675 四舍五入到小数点后两位,则会得到此结果

<代码>>>>圆(2.675, 2)
2.67

内置 round() 函数的文档说它
四舍五入到最接近的值,远离零舍入。自从
小数 2.675 正好是 2.67 和 2.68 的中间,你
可能期望这里的结果是(二进制近似值)2.68。
事实并非如此,因为当十进制字符串 2.675 转换为
二进制浮点数,再次替换为二进制
近似值,其精确值为

2.67499999999999982236431605997495353221893310546875

由于该近似值比 2.68 更接近 2.67,因此
向下舍入。

What Every Computer Scientist Should Know About Floating-Point Arithmetic.

In short - you should not rely on precise values of float numbers because of the way they are stored in the memory.

See also python docs about it - Floating Point Arithmetic: Issues and Limitations. It contains the next passage:

For example, if you try to round the value 2.675 to two decimal places, you get this

>>> round(2.675, 2)
2.67

The documentation for the built-in round() function says that it
rounds to the nearest value, rounding ties away from zero. Since the
decimal fraction 2.675 is exactly halfway between 2.67 and 2.68, you
might expect the result here to be (a binary approximation to) 2.68.
It’s not, because when the decimal string 2.675 is converted to a
binary floating-point number, it’s again replaced with a binary
approximation, whose exact value is

2.67499999999999982236431605997495353221893310546875

Since this approximation is slightly closer to 2.67 than to 2.68, it’s
rounded down.

刘备忘录 2024-12-13 11:23:22

如果您需要精确的算术,可以使用 decimal 模块:

import decimal
D=decimal.Decimal

x=D('32.50')*D('0.19')
print(x)
# 6.1750
print(x.quantize(D('0.01'),rounding=decimal.ROUND_UP))
# 6.18

y=D('32.50')*D('0.19')*D('3')
print(y)
# 18.5250
print(y.quantize(D('0.01'),rounding=decimal.ROUND_UP))
# 18.53

If you need exact arithmetic, you could use the decimal module:

import decimal
D=decimal.Decimal

x=D('32.50')*D('0.19')
print(x)
# 6.1750
print(x.quantize(D('0.01'),rounding=decimal.ROUND_UP))
# 6.18

y=D('32.50')*D('0.19')*D('3')
print(y)
# 18.5250
print(y.quantize(D('0.01'),rounding=decimal.ROUND_UP))
# 18.53
花开半夏魅人心 2024-12-13 11:23:22

使用 python 中的 Decimal 模块进行精确的浮点算术

from decimal import Decimal, ROUND_UP

value = Decimal(32.50 * 0.19 * 3)
print (value.quantize(Decimal('.01'), rounding=ROUND_UP))

Output: 18.53

Use the Decimal Module from python to do accurate floating arithmatic

from decimal import Decimal, ROUND_UP

value = Decimal(32.50 * 0.19 * 3)
print (value.quantize(Decimal('.01'), rounding=ROUND_UP))

Output: 18.53
深海不蓝 2024-12-13 11:23:22

你没有做错任何事,这也不是 Python 的错。一些十进制数字无法精确地表示为二进制浮点数。

就像您不能将 1/3 写成十进制 (0.33333....) 一样,您也不能将十进制 0.1 写成二进制(0.0001100110011001100110011001100110011001100110011...)。

解决方案A:

使用print 32.5 * 0.19 - 它会自动对结果进行四舍五入。

解决方案B:

使用十进制 模块,如果您确实需要这种精度,例如在使用货币值进行计算时。

解决方案 C:

使用 Python 3.2 或 Python 2.7,它将在交互式会话中自动对结果进行舍入。

Python 2.7.2 (default, Jun 12 2011, 14:24:46) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 32.50 * 0.19
6.175

You're doing nothing wrong, and it isn't Python's fault either. Some decimal numbers just cannot be precisely represented as binary floats.

Just like you can't write 1/3 in decimal (0.33333....), you can't write decimal 0.1 in binary (0.0001100110011001100110011001100110011001100110011...).

Solution A:

Use print 32.5 * 0.19 - it will automatically round the result.

Solution B:

Use the Decimal module if you actually need this precision, for example when calculating with monetary values.

Solution C:

Use Python 3.2 or Python 2.7 which will automatically round the result in an interactive session.

Python 2.7.2 (default, Jun 12 2011, 14:24:46) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 32.50 * 0.19
6.175
再浓的妆也掩不了殇 2024-12-13 11:23:22

我不认为这是错误的。从 Python 解释器来看:

>>> round(18.524999999999999,2)
18.52
>>> round(6.1749999999999998,2)
6.17
>>> 

在这两种情况下,被舍入的数字都小于 5,因此向下舍入。 18.52 和 6.17。

这是正确的。

我不明白的一件事是为什么你得到 6.18,而我得到 6.17。我使用的是Python 3.2.2(最新版本)

I don't think that is wrong. Take this from the Python interpreter:

>>> round(18.524999999999999,2)
18.52
>>> round(6.1749999999999998,2)
6.17
>>> 

In both cases, the number being rounded was less than 5, so it rounded down. 18.52, and 6.17.

That is correct.

One thing I don't get is why you are getting 6.18, and I get 6.17. I am using Python 3.2.2 (the latest version)

不必了 2024-12-13 11:23:22

你没有做错任何事。这是由于数字的内部表示形式造成的:

例如,尝试以下操作:

0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1

如果需要更高的精度,请使用十进制表示形式

You are not doing anything wrong. This is due to the internal representation of the numbers:

For example, try this:

0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1

If you need more precision use the decimal representation

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