具有可变精度的百分比

0 投票
6 回答
826 浏览
提问于 2025-04-15 14:41

我想显示一个百分比,保留三位小数,除非这个百分比大于99%。如果大于99%,我希望显示这个数字,保留所有的9和后面加上三个不是9的字符。

我该怎么用Python来实现这个呢?"%.8f"这种字符串格式化方法还不错,但我需要确保在最后一串9之后保留最后三个字符。

举个例子:
54.8213% 变成 54.821%
95.42332% 变成 95.423%
99.9932983% 变成 99.99330%
99.99999999992318 变成 99.9999999999232%

6 个回答

1
def ceilpowerof10(x):
    return math.pow(10, math.ceil(math.log10(x)))

def nines(x):
    return -int(math.log10(ceilpowerof10(x) - x))

def threeplaces(x):
    return ('%.' + str(nines(x) + 3) + 'f') % x

请注意,nines() 在处理那些本身就是10的幂的数字时会出错。如果想让它对所有输入都安全使用,还需要做一些额外的工作。另外,处理负数时可能也会有一些问题。

2

Mark Ransom的回答真是太棒了。只要稍微动动手,就能解决任何输入的问题。我已经把这点小工作做了。

你只需要在nines()里面加一些代码:

def nines(x):
    x = abs(x)  # avoid exception caused if x is negative
    x -= int(x)  # keep fractional part of x only
    cx = ceilpowerof10(x) - x
    if 0 == cx:
        return 0  # if x is a power of 10, it doesn't have a string of 9's!
    return -int(math.log10(cx))

这样,threeplaces()就可以处理任何情况了。下面是几个测试案例:

>>> threeplaces(0.9999357)
'0.9999357'
>>> threeplaces(1000.9999357)
'1000.9999357'
>>> threeplaces(-1000.9999357)
'-1000.9999357'
>>> threeplaces(0.9900357)
'0.99004'
>>> threeplaces(1000.9900357)
'1000.99004'
>>> threeplaces(-1000.9900357)
'-1000.99004'
3

试试这个:

import math
def format_percentage(x, precision=3):
    return ("%%.%df%%%%" % (precision - min(0,math.log10(100-x)))) % x

撰写回答