Python的舍入问题

Python的舍入问题,python,rounding,Python,Rounding,可能重复: 我在Python中有一个舍入问题。如果我计算 32.50*0.19=6.174999998 但这应该是6.175。如果我将6.174999999998四舍五入并加上两位小数,则正确显示为6.18。所以我可以接受 但如果我计算一下: 32.50*0.19*3=18.524999999999 这应该是18.525。如果我将值18.524999999999四舍五入为两位小数,则显示为18.52 应该是18.53。我做错了什么?我该如何修复它?我不认为这是错的。从Python解释器中获取以

可能重复:

我在Python中有一个舍入问题。如果我计算

32.50*0.19=6.174999998

但这应该是6.175。如果我将6.174999999998四舍五入并加上两位小数,则正确显示为6.18。所以我可以接受

但如果我计算一下:

32.50*0.19*3=18.524999999999

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


应该是18.53。我做错了什么?我该如何修复它?

我不认为这是错的。从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(最新版本)

您没有做错什么,而且。有些十进制数不能精确地表示为二进制浮点数

就像你不能用十进制(
0.33333…
)写
1/3
,你也不能用二进制(
0.0001100110011…
)写十进制
0.1

解决方案A:

使用
打印32.5*0.19
-它将自动对结果进行四舍五入

解决方案B:

如果您实际需要此精度,例如使用货币值计算时,请使用该模块

解决方案C:

使用Python3.2或Python2.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

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

另请参见python文档中关于它的内容-。它包含下一段:

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

>>圆形(2.675,2)

2.67

内置round()函数的文档说明 舍入到最接近的值,舍入到远离零的位置。自从 小数点2.675正好介于2.67和2.68之间,你知道吗 这里的结果可能是(二元近似值)2.68。 不是,因为当十进制字符串2.675转换为 二进制浮点数,它再次被二进制替换 近似值,其精确值为

2.67499999999998223643160599749535322183310546875

因为这个近似值比2.68稍微接近2.67,所以它是 四舍五入


你没有做错什么。这是由于数字的内部表示:

例如,尝试以下方法:

0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1
如果需要更高的精度,请使用十进制表示法

使用python中的模块执行精确的浮点算术运算

from decimal import Decimal, ROUND_UP

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


如果需要精确的算法,可以使用以下模块:


尝试
打印32.50*0.19
打印32.50*0.19*3
。Python知道如何正确显示这些浮点值。在这种情况下,您就可以像计算机一样使用浮点存储接近正确的(十进制)值。如果您确实需要确切的答案(您不需要),请使用
Decimal.Decimal
-1。在StackOverflow的搜索中键入这篇文章的标题很容易找到这个问题的答案-1表示不努力做到这一点。因为他没有确切的数字,这只是他真正得到的数字的
repr
。他并不真正需要
Decimal
,但他不明白浮点是如何工作的。@agf:你怎么知道他需要什么?他完全有可能是在和钱打交道,而这不应该用浮点来做。确切地说,我是在和钱打交道,所以我会试试这个,谢谢:)他其实并不需要小数,他只是不明白浮点是怎么工作的。OP问如何修它(
Decimal
)。该链接还解释了OP出现此问题的原因。虽然文档和教程都没有更新,但在Python 2.7.4
中,round(2.675,2)
现在将给出预期的
2.68
。@Neftas:你是根据什么提出这一主张的?在我使用Python 2.7.6的机器上,
round(2.675,2)
向下舍入,正如文档中所述。自Python2.7.0以来,
round
算法没有任何重大变化。你说得对,@MarkDickinson。在我写这篇文章的时候,我当然试过了,但是现在我新安装的Python 2.7.3已经完成了。所以这可能是我的一个错误。@Neftas:好吧,这是有道理的。
round
函数的历史相当混乱:在Python 2.6中,它通常会将一半大小写取整,在Python 2.7中总是将一半大小写取整,在Python>=3.1中总是将一半大小写取整到最接近的偶数结果。当然,多亏了底层的二进制表示法,在十进制中看起来像中间格的东西不一定是实际的中间格。显然,你不希望在代码中依赖它。对于这种除法,最好总是使用
decimal
模块(如Python参考中所建议的)。
Output: 18.53
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