【问题标题】:Python Decimal formatting wrong behavior?Python十进制格式错误行为?
【发布时间】:2013-08-02 19:07:52
【问题描述】:

我试图在使用 '%.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 rounding number-formatting


    【解决方案1】:

    您的问题是可重复的。作为一种解决方法,您可以使用较新的库。

        >>> '{0:.2f}'.format( Decimal('236.1650') )
        '236.16'
        >>> '{0:.2f}'.format( Decimal('111.1650') )
        '111.16'
    

    【讨论】:

      【解决方案2】:

      发生这种情况是因为浮点值无法准确表示。参考文档floating point arithmetic.

      或者,为了让您了解发生了什么,请输入:

      >>> Decimal(111.1650)
      Decimal('111.1650000000000062527760746888816356658935546875')
      >>> Decimal(236.1650)
      Decimal('236.164999999999992041921359486877918243408203125')
      

      问题在于,在您的情况下,浮点数在 .005 边界附近并不精确。您刚刚遇到了一个数字将略高于 0.005(因此为上限)而另一个数字略低于并被限制的情况。

      【讨论】:

        【解决方案3】:

        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 格式方法相对于旧式基于 % 格式的一大胜利。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-14
          • 2022-01-20
          • 1970-01-01
          • 2021-11-20
          • 1970-01-01
          相关资源
          最近更新 更多