在使用“%.2f”格式化小数时,我试图获得一个一致的值。然而,结果令我惊讶。相同的十进制值,不同的四舍五入。知道我做错了什么吗?
>>> from decimal import Decimal
>>> x = Decimal('111.1650')
>>> print '%.2f' % x
111.17
>>> y = Decimal('236.1650')
>>> print '%.2f' % y
236.16
谢谢
在使用“%.2f”格式化小数时,我试图获得一个一致的值。然而,结果令我惊讶。相同的十进制值,不同的四舍五入。知道我做错了什么吗?
>>> from decimal import Decimal
>>> x = Decimal('111.1650')
>>> print '%.2f' % x
111.17
>>> y = Decimal('236.1650')
>>> print '%.2f' % y
236.16
谢谢
Python 的百分比样式格式不理解Decimal
对象:当您格式化时,会隐式转换为浮点数。碰巧最接近您的x
值的可表示二进制浮点数是:
>>> print Decimal(float(x))
111.1650000000000062527760746888816356658935546875
这比111.165
中途情况要大一点,所以它四舍五入。同样,对于y
,最终被格式化的值是这个:
>>> print Decimal(float(y))
236.164999999999992041921359486877918243408203125
在这种情况下,为输出格式化的值刚好低于中间值,因此它向下舍入。
为避免隐式转换,可以使用.format
格式化方法:
>>> "{0:.2f}".format(Decimal('111.1650'))
'111.16'
>>> "{0:.2f}".format(Decimal('236.1650'))
'236.16'
请注意,您可能仍然不喜欢所有结果:
>>> "{0:.2f}".format(Decimal('236.1750'))
'236.18'
默认情况下,这种格式格式使用半舍入到偶数舍入模式。事实上,它从当前Decimal
上下文中获取舍入模式,所以你可以这样做:
>>> from decimal import getcontext, ROUND_HALF_UP
>>> getcontext().rounding=ROUND_HALF_UP
>>> "{0:.2f}".format(Decimal('236.1750'))
'236.18'
>>> "{0:.2f}".format(Decimal('236.1650')) # Now rounds up!
'236.17'
作为一般评论,能够为用户定义的类实现自定义格式是新.format
格式格式方法相对于旧格式格式的一大胜利%
。
你的问题是可重复的。作为一种解决方法,您可以使用较新的库。
>>> '{0:.2f}'.format( Decimal('236.1650') )
'236.16'
>>> '{0:.2f}'.format( Decimal('111.1650') )
'111.16'
发生这种情况是因为浮点值无法准确表示。请参阅文档浮点运算。
或者,为了让您了解发生了什么,请输入:
>>> Decimal(111.1650)
Decimal('111.1650000000000062527760746888816356658935546875')
>>> Decimal(236.1650)
Decimal('236.164999999999992041921359486877918243408203125')
问题是在您的情况下,浮点数在 .005 边界附近并不精确。您刚刚遇到了这样一种情况,即一个数字将略高于 0.005(因此为上限),而另一个数字略低于并被限制。