【问题标题】:How can I format a decimal to always show 2 decimal places?如何格式化小数以始终显示 2 个小数位?
【发布时间】:2011-01-01 00:34:04
【问题描述】:

我要显示:

4949.00

和:

54.954.90

无论小数的长度或是否有任何小数位,我都想显示带有 2 个小数位的Decimal,并且我想以一种有效的方式进行。目的是显示货币价值。

例如,4898489.00

【问题讨论】:

  • 我想这可能意味着 OP 正在使用 decimal.Decimal 并且对十进制上下文的精度不满意,这将精度限制为 n 位,如“严格意义上的 n 位精度”(例如 '123.456 ' 变为 Decimal('1.2E+2')) 而不是“小数部分中的 n 位数字”(对于 Decimal('123.45'))...请参阅我的答案以尝试对此有所帮助。 ;-)
  • 是的,它们是为了金钱价值。

标签: python string-formatting


【解决方案1】:

您应该使用new format specifications 来定义您的价值应该如何表示:

>>> from math import pi  # pi ~ 3.141592653589793
>>> '{0:.2f}'.format(pi)
'3.14'

文档有时可能有点迟钝,所以我推荐以下更易读的参考资料:

Python 3.6 引入了literal string interpolation(也称为 f-strings),所以现在您可以将上面的内容写得更简洁:

>>> f'{pi:.2f}'
'3.14'

【讨论】:

  • @Droogans:Euh...format 确实返回 str,而不是 floatprint type({0:.2f}".format(pi)) 返回 <type 'str'>
  • 糟糕。单词return 上的动词重载。请在心里把它改成prints。
  • 如果不想使用数字占位符:"{:.2f}".format(pi)
  • 0: 有什么作用?我假设 . 是 python 字符串的一部分
  • @information_interchange: 0 表示它是传递给format 函数的第一个参数。如果您想打印类似'{0} is bigger than {1}'.format(5, 4) 的内容,请参阅stackoverflow.com/a/517471 了解详情。
【解决方案2】:

Python 文档的String Formatting Operations 部分包含您正在寻找的答案。简而言之:

"%0.2f" % (num,)

一些例子:

>>> "%0.2f" % 10
'10.00'
>>> "%0.2f" % 1000
'1000.00'
>>> "%0.2f" % 10.1
'10.10'
>>> "%0.2f" % 10.120
'10.12'
>>> "%0.2f" % 10.126
'10.13'

【讨论】:

  • % 之后不需要0,也不需要将num 包裹在tuple 中。
  • 实际上,将 num 包装在一个元组中是一种编码约定,以防止在字符串格式化期间在参数上出现鸭子输入错误。在这种情况下,它对浮点转换没有任何影响,但它可以防止在转换为字符串时出现意外的类型错误。考虑r = 1; "%s" % r; r = (1, 2); "%s" % rr = 1; "%s" % (r,); r = (1,2 ); "%s" % (r,)。因此,python 中最复杂的编码风格现在使用无条件元组(并且 Python 3 弃用了整个字符串格式化方法,因为它容易出错)。
  • 另外,作为一个有数学背景的人,“裸”十进制表示法很丑陋。领先的 0 不会伤害任何东西,并且看起来更好。 :)
  • 美学上没有什么不同。最重要的是,无论如何,0 是默认值。如果提供美观的代码,那么提供默认值绝对没有害处。有趣的是,有多少开发人员选择不(不能?)区分正确性和风格。 ://
【解决方案3】:

我想您可能正在使用来自decimal 模块的Decimal() 对象? (如果您需要任意大数字的小数点之外的两位精度,那么您绝对应该这样做,这就是您的问题标题所暗示的......)

如果是这样,文档的 Decimal FAQ 部分有一个可能对您有用的问题/答案对:

问。在具有两位小数的定点应用程序中,某些输入有很多位并且需要四舍五入。其他人不应该有多余的数字,需要进行验证。应该使用什么方法?

A. quantize() 方法四舍五入到固定的小数位数。如果设置了不精确陷阱,它对验证也很有用:

>>> TWOPLACES = Decimal(10) ** -2       # same as Decimal('0.01')
>>> # Round to two places
>>> Decimal('3.214').quantize(TWOPLACES)
Decimal('3.21')
>>> # Validate that a number does not exceed two places
>>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Decimal('3.21')
>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Traceback (most recent call last):
   ...
Inexact: None

下一个问题是

问。一旦我有了有效的两个位置输入,我如何在整个应用程序中保持该不变量?

如果您需要这个问题的答案(以及许多其他有用的信息),请参阅the aforementioned section of the docs。此外,如果您将Decimals 的精度保留在小数点后两位数(这意味着将所有数字保留在小数点左侧,将两位数保留在小数点右侧,仅此而已.. .),然后使用str 将它们转换为字符串即可:

str(Decimal('10'))
# -> '10'
str(Decimal('10.00'))
# -> '10.00'
str(Decimal('10.000'))
# -> '10.000'

【讨论】:

  • 哦,忘了在答案中提到效率......但我想我无论如何都不是专家。我看不出为什么保留固定数量的“小数位”会特别低效——尽管对数字执行的任何操作都可能需要对结果进行舍入操作以使其符合要求......对于为了提高效率,这可能应该尽可能少地完成——就像在为用户序列化/打印之前一样。
【解决方案4】:
>>> print "{:.2f}".format(1.123456)
1.12

您可以将2f 中的2 更改为您想要显示的任意小数点数。

编辑:

来自Python3.6,翻译为:

>>> print(f"{1.1234:.2f}")
1.12

【讨论】:

    【解决方案5】:

    您可以这样使用string formatting operator

    num = 49
    x = "%.2f" % num  # x is now the string "49.00"
    

    我不确定您所说的“高效”是什么意思——这几乎肯定不是您的应用程序的瓶颈。如果您的程序运行缓慢,请先对其进行分析以找到热点,然后对其进行优化。

    【讨论】:

    • 我认为名为“f”的变量可能会让一些人感到困惑。对于下面的 Travis 示例,最好将其称为其他名称。
    【解决方案6】:

    .format 是一种处理变量格式的更易读的方式:

    '{:.{prec}f}'.format(26.034, prec=2)
    

    【讨论】:

    • 我不知道你可以嵌套这样的格式。很酷。
    【解决方案7】:

    在 python 3 中,这样做的一种方法是

    '{:.2f}'.format(number)
    

    【讨论】:

      【解决方案8】:

      如果你有多个参数,你可以使用

       print('some string {0:.2f} & {1:.2f}'.format(1.1234,2.345))
       >>> some string 1.12 & 2.35
      

      【讨论】:

        【解决方案9】:

        OP 总是想要两个小数位显示,因此像所有其他答案所做的那样,显式调用格式化函数还不够好。

        正如其他人已经指出的那样,Decimal 适用于货币。但Decimal 显示所有小数位。所以,覆盖它的显示格式化程序:

        class D(decimal.Decimal):
            def __str__(self):
                return f'{self:.2f}'  
        

        用法:

        >>> cash = D(300000.991)
        >>> print(cash)
        300000.99
        

        简单。

        编辑:

        显示至少两位小数但截断有效数字:

        class D(decimal.Decimal):
            def __str__(self):
                """Display at least two decimal places."""
                result = str(self)
                i = result.find('.')
                if i == -1:
                     # No '.' in self. Pad with '.00'.
                     result += '.00'
                elif len(result[i:]) == 2:
                     # One digit after the decimal place. Pad with a '0'.
                     result += '0'
                return result
        

        我希望 Python 的未来版本将改进数字格式以允许最小小数位。在 Excel 的数字格式中,# 之类的符号。

        【讨论】:

          【解决方案10】:

          如果您将其用于货币,并且还希望该值由 , 分隔,您可以使用

          $ {:,.f2}.format(currency_value).

          例如:

          currency_value = 1234.50

          $ {:,.f2}.format(currency_value)-->$ 1,234.50

          这是我前段时间写的一段代码:

          print("> At the end of year " + year_string + " total paid is \t$ {:,.2f}".format(total_paid))

          > At the end of year   1  total paid is         $ 43,806.36
          > At the end of year   2  total paid is         $ 87,612.72
          > At the end of year   3  total paid is         $ 131,419.08
          > At the end of year   4  total paid is         $ 175,225.44
          > At the end of year   5  total paid is         $ 219,031.80   <-- Note .80 and not .8
          > At the end of year   6  total paid is         $ 262,838.16
          > At the end of year   7  total paid is         $ 306,644.52
          > At the end of year   8  total paid is         $ 350,450.88
          > At the end of year   9  total paid is         $ 394,257.24
          > At the end of year  10  total paid is         $ 438,063.60   <-- Note .60 and not .6
          > At the end of year  11  total paid is         $ 481,869.96
          > At the end of year  12  total paid is         $ 525,676.32
          > At the end of year  13  total paid is         $ 569,482.68
          > At the end of year  14  total paid is         $ 613,289.04
          > At the end of year  15  total paid is         $ 657,095.40   <-- Note .40 and not .4  
          > At the end of year  16  total paid is         $ 700,901.76
          > At the end of year  17  total paid is         $ 744,708.12
          > At the end of year  18  total paid is         $ 788,514.48
          > At the end of year  19  total paid is         $ 832,320.84
          > At the end of year  20  total paid is         $ 876,127.20   <-- Note .20 and not .2
          

          【讨论】:

            【解决方案11】:

            这与您可能已经看到的解决方案相同,但这样做会更清晰:

            &gt;&gt;&gt; num = 3.141592654

            &gt;&gt;&gt; print(f"Number: {num:.2f}")

            【讨论】:

              【解决方案12】:

              向您展示如何做到这一点的最简单方法示例是:

              代码:

              >>> points = 19.5 >>> total = 22 &gt;&gt;&gt;'Correct answers: {:.2%}'.format(points/total) `

              输出:正确答案:88.64%

              【讨论】:

                【解决方案13】:

                怎么样

                print round(20.2564567 , 2)    >>>>>>>        20.25
                
                
                print round(20.2564567 , 4)    >>>>>>>        20.2564
                

                【讨论】:

                  猜你喜欢
                  • 2011-09-02
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-05-03
                  • 1970-01-01
                  • 2016-10-04
                  • 1970-01-01
                  相关资源
                  最近更新 更多