【问题标题】:Present a Decimal in the most readable format以最易读的格式显示十进制
【发布时间】:2021-09-14 21:19:56
【问题描述】:

所以我正在尝试创建一个以最易读的格式返回字符串化十进制的函数。这些是我为自己创建的要求:

  1. 如果数字的绝对指数大于等于9,则应使用科学计数法表示(例如25000000000 -> 2.5E+90.0000000036 -> 3.6E-9
  2. 否则,该数字应以标准表示法十进制表示,并带有最少的尾随零(例如103.400000 -> 103.40.000005600 -> 0.0000056

目前,我正在使用从 this answer 修改的一些代码,但我真的找不到一种方法来让它完全符合我的要求。

目前,我的解决方案如下:

def stringifyDecimal(d: Decimal):
    # If d is within a reasonable range for printing as a normal number
    a = abs(math.log10(abs(d)))
    if a < 9:
        r = d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
    else:
        r = d.normalize()
    return str(r)

这适用于较大的数字:

  • stringifyDecimal(D('1E5')) -&gt; '10000'
  • stringifyDecimal(D('1E9')) -&gt; '1E+9'

但是对于非常小的分数,它总是以科学计数法返回:

  • stringifyDecimal(D('1E-7')) -&gt; '1E-7'

这是因为第 5 行的 ...else d.normalize() 部分返回一个 Decimal,默认情况下将字符串化为科学记数法。遗憾的是,格式化选项不适用于 they require me to know the exact precision that I want to format to

有没有一种方法可以强制 Decimal 类型以小数而不是科学计数法显示非常小的分数?

【问题讨论】:

  • 得到a的值后可以做一些打印调试。并检查它1E-7
  • 那么,你的下限是多少?大概你不希望23E-23 完全显示出来。
  • @xcodz-dot 我已经这样做了,它按预期工作。
  • @TimRoberts 我的下限也是 9。1E-8 应该打印为十进制,但1E-9 应该用科学计数法打印。
  • 那么问题出在 if 块内

标签: python decimal string-formatting


【解决方案1】:

顺便说一句,由于日志,您的代码失败为 0。看看你对此有何看法。对于 10-7 和 10-9 之间的值,我乘以 100,转换为字符串,然后插入两个零:

import math
from decimal import Decimal

def stringifyDecimal(d: Decimal):
    # If d is within a reasonable range for printing as a normal number
    if not d:
        return "0"
    a = math.log10(abs(d))
    if 0 < a < 9:
        r = d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
        r = str(r)
    elif -8 < a < -6:
        r = str((d*100).normalize())
        r = r[:2] + '00' + r[2:]
    else:
        r = d.normalize()
        r = str(r)
    return r

tests = [
    "12e12", "11e11", "10e10", "9e9", "8e8", "7e7", "6e6", "5e5", "4e4", "3e3", "2e2", "1e1",
    "0",
    "1e-1", "2e-2", "3e-3", "4e-4", "5e-5", "6e-6", "7e-7", "8e-8", "9e-9", "10e-10"
]

for test in tests:
    print(stringifyDecimal(Decimal(test)))

输出:

1.2E+13
1.1E+12
1E+11
9E+9
800000000
70000000
6000000
500000
40000
3000
200
10
0
0.1
0.02
0.003
0.0004
0.00005
0.000006
0.0000007
0.00000008
9E-9
1E-9

【讨论】:

  • 这看起来真的很棒!一个小的修复可能是将elif -8 &lt; a &lt; -6: 替换为elif -8 &lt;= a &lt; -6:,否则它对于输入1E-8 将无法正常工作。非常感谢!!!
  • 谢天谢地,我不需要担心前导零,因为它在程序的前面已经处理过(当它首先尝试以分数表示时)
【解决方案2】:

好吧,我发现最有效的方法是使用字符串格式化。

d = Decimal('152')
print(f"{d:f}") # Format as a standard decimal
print(f"{d:e}") # Format in scientific notation

由此,我的解决方案如下:

def strDecimal_Sci(d: Decimal) -> str:
    return f"{d.normalize():e}"

def strDecimal_Norm(d: Decimal) -> str:
    return f"{d.normalize():f}"

def stringifyDecimal(d: Decimal) -> str:
    if d == 0: return "0"
    a = abs(math.log10(abs(d)))
    if a < 9:
        return strDecimal_Norm(d)
    else:
        return strDecimal_Sci(d)

【讨论】:

    猜你喜欢
    • 2021-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 2013-01-09
    • 2013-02-05
    • 1970-01-01
    相关资源
    最近更新 更多