【问题标题】:round down to 2 decimal in python在python中向下舍入到小数点后2位
【发布时间】:2016-12-29 16:42:55
【问题描述】:

我需要四舍五入,它应该是小数点后两位。
尝试了以下,

a = 28.266
print round(a, 2)

28.27

但预期值仅为 28.26。

【问题讨论】:

  • 你想截断。看看这里:stackoverflow.com/questions/8595973/…
  • 如果您参考最佳答案,@zinjaai 是正确的一半。但是,请考虑评论 '%.3f'%(1324343032.3243) and '%.3f'%(1324343032.3245) give different results 这是因为最高答案实际上相当于四舍五入。我会在这里使用@Psidom 的答案。

标签: python rounding


【解决方案1】:

看来你需要floor:

import math
math.floor(a * 100)/100.0

# 28.26

【讨论】:

    【解决方案2】:

    您似乎想要截断,而不是四舍五入。

    一种简单的方法是将楼层除法// 和常规除法/ 结合起来:

    >>> a = 28.266
    >>> a // 0.01 / 100
    28.26
    

    除了常规除法之外,您还可以乘法(如 cmets 中 cmc 所述):

    >>> a // 0.01 * 0.01
    28.26
    

    同样,您可以创建一个函数来向下舍入到其他更多/更少的小数。但由于浮点数是不精确的数字,这可能会导致不准确。

    def round_down(value, decimals):
        factor = 1 / (10 ** decimals)
        return (value // factor) * factor
    
    print(round_down(28.266, 2))
    # 28.26
    

    但正如所说的并不完全准确:

    for i in range(0, 8):
        print(i, round_down(12.33333, i))
    
    0 12.0
    1 12.3
    2 12.33
    3 12.333
    4 12.333300000000001 # weird, but almost correct
    5 12.33332           # wrong
    6 12.33333
    7 12.33333
    

    还有其他(更精确的)方法:

    使用fraction 模块的解决方案

    fraction 可以表示比float 更精确的十进制数。然后可以使用 Psidom 提到的“乘法,然后乘法,然后除法”,但精度要高得多:

    import fractions
    import math
    
    a = 28.266
    
    def round_down(value, decimals):
        factor = 10 ** decimals
        f = fractions.Fraction(value)
        return fractions.Fraction(math.floor(f * factor),  factor)
    
    print(round_down(28.266, 2))
    # 1413/50  <- that's 28.26
    

    并使用我对花车所做的测试:

    for i in range(0, 8):
        print(i, round_down(12.33333, i))
    
    0 12
    1 123/10
    2 1233/100
    3 12333/1000
    4 123333/10000
    5 1233333/100000
    6 1233333/100000
    7 1233333/100000
    

    但是,创建Fraction 不会神奇地修复不精确的float,因此通常应该从字符串或“分子-分母对”而不是浮点数创建Fraction

    使用decimal 模块的解决方案

    您还可以使用decimal 模块,它提供了多种舍入模式,包括向下舍入。

    对于这个演示,我使用上下文管理器来避免全局更改小数舍入模式:

    import decimal
    
    def round_down(value, decimals):
        with decimal.localcontext() as ctx:
            d = decimal.Decimal(value)
            ctx.rounding = decimal.ROUND_DOWN
            return round(d, decimals)
    
    print(round_down(28.266, 2))  # 28.26
    

    这为舍入提供了更合理的结果:

    for i in range(0, 8):
        print(i, round_down(12.33333, i))
    
    0 12
    1 12.3
    2 12.33
    3 12.333
    4 12.3333
    5 12.33333
    6 12.333330
    7 12.3333300
    

    Fraction 一样,应从字符串创建Decimal 以避免中间不精确的浮点数。但与Fraction 不同,Decimal 的精度有限,因此对于具有大量有效数字的值也会变得不精确。

    但是,“四舍五入”只是可用选项之一。 available rounding modes 的列表很广泛:

    舍入模式

    decimal.ROUND_CEILING 向无穷大旋转。

    decimal.ROUND_DOWN 向零舍入。

    decimal.ROUND_FLOOR 向 -Infinity 舍入。

    decimal.ROUND_HALF_DOWN四舍五入,平局趋近于零。

    decimal.ROUND_HALF_EVEN 舍入到最接近的整数,平数接近最接近的偶数。

    decimal.ROUND_HALF_UP 舍入到最近的平局,从零开始。

    decimal.ROUND_UP 从零取整。

    decimal.ROUND_05UP 如果舍入到零后的最后一位是 0 或 5,则从零舍入;否则向零舍入。

    【讨论】:

    • @user2682863 我的示例中提到的一些解决方案受到浮点不精确的影响。但我注意到,在每种方法上,但最后两个带有小数和小数的解决方案不受影响。
    【解决方案3】:

    使用 Python 3,您可以使用 quantize()

    from decimal import *    
    >>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
    Decimal('7.32')
    

    【讨论】:

      【解决方案4】:

      试试这个:

      import math
      a = 28.266
      print((math.floor(a * 100)) / 100.0)
      

      输出:

      28.26
      

      【讨论】:

        【解决方案5】:

        这是一个不受浮点精度错误影响的简单函数

        def truncate_float(n, places):
            return int(n * (10 ** places)) / 10 ** places
        

        测试:

        >>> truncate_float(28.266, 3)
        28.266
        >>> truncate_float(28.266, 2)
        28.26
        >>> truncate_float(28.266, 1)
        28.2
        

        【讨论】:

          【解决方案6】:

          一般来说,还有一种更简单的方法,即在四舍五入前减去少量,如下所示:

          a = 28.269
          digits = 2
          print(round(a - 0.5/10**digits, digits))
          

          这是基于直觉,将浮点数舍入到最接近的整数的一种方法是添加 0.5,然后截断。上述解决方案通过减去所需精度允许的最小“刻度”的一半,然后四舍五入来做相反的事情。

          【讨论】:

          • 如果你使用digits = 3 那么结果是28.268 - 这是不正确的
          • 你说得对,某些值有时会不正确。这是因为round() 使用了round half even mode 吗?
          • 我认为不同之处在于浮点数不精确,a - 0.5/10**digits 实际上是 28.268499999999999516830939683132... 对于 digits=3。然而28.269 也不能完全表示为浮点数:28.268999999999998351540853036568...。这就是为什么我的回答还显示了如何使用 FractionDecimal 来舍入该值,因为小数“非常精确”而小数几乎总是“足够精确”(至少如果输入以字符串形式给出(而不是浮动)。
          【解决方案7】:

          您可以在代码中使用的简单函数。此函数也可用于整数楼层数。

          import math
          def floorDecimal(number, decimal):
              return math.floor(number * pow(10, decimal))/pow(10, decimal)
          

          使用示例:

          number = 256.789
          newNumber = floorDecimal(number, 2) # newNumber is 256.78
          newNumber = floorDecimal(number, -2) # newNumber is 200
          

          【讨论】:

            【解决方案8】:

            这是我用 f 表示浮点数和 d 表示小数位数的函数

            from math import floor
            
            def floor_decimal(f, d):
                n = 10 ** d
                return floor(f * n) / n
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-06-28
              • 1970-01-01
              • 2012-11-07
              • 1970-01-01
              • 2013-07-02
              • 1970-01-01
              相关资源
              最近更新 更多