0

我想显示一个小数点后三位的百分比,除非它大于 99%。然后,我想显示所有可用的 9 加上 3 个非 9 字符的数字。

我怎么能用 Python 写这个?字符串格式工作得很好,但我需要在最后一个九的"%.8f"字符串之后保留最后三个字符。

所以:
54.8213% -> 54.821%
95.42332% -> 95.423%
99.9932983% -> 99.99330%
99.99999999992318 -> 99.9999999999232%

4

6 回答 6

3

试试这个:

import math
def format_percentage(x, precision=3):
    return ("%%.%df%%%%" % (precision - min(0,math.log10(100-x)))) % x
于 2009-09-29T20:47:25.307 回答
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'
于 2009-09-29T21:58:24.757 回答
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 的幂开头的数字上引发错误,要使其对所有输入都安全,还需要做更多的工作。负数也可能存在一些问题。

于 2009-09-29T20:32:52.247 回答
0

试试这个:

def print_percent(p):    
    for i in range(30):
        if p <= 100. - 10.**(-i):
            print ("%." + str(max(3,3+i-1)) + "f") % p
            return

或者如果您只想检索字符串

def print_percent(p):    
    for i in range(20):
        if p <= 100. - 10.**(-i):
            return ("%." + str(max(3,3+i-1)) + "f") % p
于 2009-09-29T20:29:03.893 回答
0

我非常有信心使用标准格式这是不可能的。我建议使用类似以下的内容(C# 之类的伪代码)。特别是我建议依靠字符串运算而不是使用数学代码,因为可能存在许多精度和舍入问题。

string numberString = number.ToStringWithFullPrecision();

int index = numberString.IndexOf('.');

while ((index < numberString.Length - 1) && (numberString[index + 1] == '9'))
{
    index++;
}

WriteLine(number.PadRightWithThreeZeros().SubString(0, index + 4));

如果你喜欢正则表达式,你可以使用它们。采用以下表达式并将其与填充三个零的完整精度数字字符串匹配,您就完成了。

^([0-9]|[1-9][0-9]|100)\.(9*)([0-8][0-9]{2})

我刚刚意识到这两个建议都可能导致舍入错误。99.91238123变成99.9123它应该变成的时候99.9124- 所以最后一个数字需要额外的更正。很容易做到,但让我的建议更加丑陋。这与优雅而智能的算法相去甚远。

于 2009-09-29T20:31:52.843 回答
0
 def ilike9s(f):
   return re.sub(r"(\d*\.9*\d\d\d)\d*",r"\1","%.17f" % f)

所以...

>>> ilike9s(1.0)
'1.000'
>>> ilike9s(12.9999991232132132)
'12.999999123'
>>> ilike9s(12.345678901234)
'12.345'

别忘了import re

于 2009-09-29T21:35:57.590 回答