以最易读的格式呈现 Decimal

Present a Decimal in the most readable format

所以我正在尝试创建一个函数,该函数 returns 是最易读格式的字符串化小数。这些是我为自己创建的要求:

  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)

这适用于较大的数字:

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

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

有没有办法强制小数类型将非常小的分数显示为小数而不是科学记数法?

顺便说一句,由于日志,您的代码因 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

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

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)