以可读性最强的格式显示小数



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

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

目前,我正在使用从这个答案中修改的一些代码,但我真的看不出有什么方法可以让它完全符合我的要求。

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

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')) -> '10000'
  • stringifyDecimal(D('1E9')) -> '1E+9'

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

  • stringifyDecimal(D('1E-7')) -> '1E-7'

这是因为第5行的...else d.normalize()部分,它返回一个Decimal,默认情况下该Decimal将字符串化为科学记数法。遗憾的是,格式化选项不适用于此,因为它们需要我知道我想要格式化的确切精度。

有没有一种方法可以强制Decimal类型将非常小的分数显示为十进制,而不是科学记数法?

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