【问题标题】:How to round a Python Decimal to 2 decimal places?如何将 Python Decimal 舍入到小数点后 2 位?
【发布时间】:2014-06-28 07:05:00
【问题描述】:

我有一个 python Decimal(货币金额),我想四舍五入到小数点后两位。我尝试使用常规的 round() 函数来执行此操作。不幸的是,这会返回一个浮点数,这使得继续不可靠:

>>> from decimal import Decimal
>>> a = Decimal('1.23456789')
>>> type(round(a, 2))
<type 'float'>

在十进制模块中,我看到了一些与舍入有关的事情:

  • ROUND_05UP
  • ROUND_CEILING
  • ROUND_DOWN
  • ROUND_FLOOR
  • ROUND_HALF_DOWN
  • ROUND_HALF_EVEN
  • ROUND_HALF_UP
  • ROUND_UP
  • 圆角

我认为这些都没有真正提供我想要的东西(或者我错了吗?)。

所以我的问题是:有人知道我如何可靠地将 Python 小数四舍五入到小数点后 2 位,以便我可以继续使用小数吗?欢迎所有提示!

【问题讨论】:

  • 使用整数(美分而不是美元)不是更有意义吗?那也会更快。
  • 设置十进制数的精度:decimal.getcontext().prec=2.
  • @ooga:它处理有效位数,而不是小数位数,因此不合适(它将12345678变成1.2E+7,但仅在对其进行计算之后,而不是在定义之后)。
  • @TimPietzcker 我明白了。在这种情况下,我同意整数是最好的。
  • 值得注意的是,round 确实使用 Python 3 直接返回了一个 Decimal 实例;它仅在 Python 2 上转换为 float。尽管如此,如果您想要除默认的ROUND_HALF_EVEN 舍入模式以外的任何其他内容,您仍然需要quantize。

标签: python floating-point decimal rounding floating-point-precision


【解决方案1】:

更多基于@countinglambdastosleep 答案的 Pythonic 代码

from decimal import Decimal, ROUND_HALF_EVEN

def decimalize(n, prec=8):
    n = n if isinstance(n, Decimal) else Decimal(n)
    fmt = ".{}1".format("0" * (prec - 1))
    return n.quantize(Decimal(fmt), rounding=ROUND_HALF_EVEN)

为什么是ROUND_HALF_EVEN?你可能会找到答案here

【讨论】:

    【解决方案2】:

    不知道为什么他们没有内置功能,但我做了一个。 我知道它在技术上不是“trueRound”,但如果你愿意,你可以改变它。 在 python 3.9 上测试

        def trueRound(num: float or str, decimalPlaces: int) -> float:
            a = Decimal(str(num))
            places_str = "0."
            for i in range(decimalPlaces - 1):
                places_str += "0"
            places_str += "1"
            PLACES = decimal.Decimal(places_str)
            result = a.quantize(PLACES)
            return float(result)
    

    【讨论】:

    • 对不起,你必须这样做:从十进制导入十进制导入十进制。我知道有一个 Decimal() 和另一个 decimal.Decimal 不是很好,但我不确定我是否可以编辑我的答案。
    【解决方案3】:

    我想到了这个:

    import decimal
    decimal.Decimal(str(round(a, 2)))
    

    但我不知道它有多快。

    【讨论】:

      【解决方案4】:

      如果您使用的是 Jupyter Notebook,只需添加魔术函数 %precision 2 即可获得 2 位小数,依此类推。

      但如果您的值不是 float() 类型,那么您可以使用以下内容:

       from decimal import getcontext, Decimal
       getcontext().prec = 2
       # for example, take integer value
       mynum = 2
       type(mynum) # Int
       print round(Decimal(mynum), 2) # 10.0
      

      【讨论】:

      • 在 Jupyter Notebook 中,%precision 似乎只为浮点值设置漂亮打印精度,而不是十进制值。
      • 另外,getcontext().prec = 2 将导致 Decimal 运算保留 2 个有效数字,而不是 2 个有效小数位。例如。 Decimal('1') * Decimal('123') 给Decimal('1.2E+2')。
      【解决方案5】:

      你尝试的第一个对我来说效果很好。

      import decimal
      
      type(round(decimal.Decimal('1.23456789'),2))
      

      &lt;class 'decimal.Decimal'&gt;

      【讨论】:

      • round 将使结果成为float 类的对象
      【解决方案6】:

      你可以使用quantize() method:

      >>> import decimal
      >>> decimal.getcontext().prec = 20
      >>> a = decimal.Decimal(321.12345)
      >>> a
      Decimal('321.12344999999999117790139280259609222412109375')
      >>> TWO_PLACES = decimal.Decimal("0.01")
      >>> a.quantize(TWO_PLACES)
      Decimal('321.12')
      

      【讨论】:

        猜你喜欢
        • 2010-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-03
        • 1970-01-01
        • 2013-08-14
        • 2018-01-17
        相关资源
        最近更新 更多