Python字符串.format()函数如何实现百分号格式化且不四舍五入?

28
在下面的例子中,我想将数字格式化为1位小数,但是Python似乎喜欢将数字四舍五入,有没有办法让它不进行四舍五入?
>>> '{:.1%}'.format(0.9995)
'100.0%'
>>> '{:.2%}'.format(0.9995)
'99.95%'
5个回答

19

如果您想始终向下舍入(而不是向最接近的精度舍入),则可以使用math.floor()函数明确地这样做:

from math import floor

def floored_percentage(val, digits):
    val *= 10 ** (digits + 2)
    return '{1:.{0}f}%'.format(digits, floor(val) / 10 ** digits)

print floored_percentage(0.995, 1)

演示:

>>> from math import floor
>>> def floored_percentage(val, digits):
...     val *= 10 ** (digits + 2)
...     return '{1:.{0}f}%'.format(digits, floor(val) / 10 ** digits)
... 
>>> floored_percentage(0.995, 1)
'99.5%'
>>> floored_percentage(0.995, 2)
'99.50%'
>>> floored_percentage(0.99987, 2)
'99.98%'

2

在Python 3.6+中,您可以使用格式化字符串字面量(也称为f-strings)。这比str.format更高效。此外,您可以使用更高效的地板除法代替math.floor。在我看来,语法也更易读。

以下是两种方法供比较。

from math import floor
from random import random

def floored_percentage(val, digits):
    val *= 10 ** (digits + 2)
    return '{1:.{0}f}%'.format(digits, floor(val) / 10 ** digits)

def floored_percentage_jpp(val, digits):
    val *= 10 ** (digits + 2)
    return f'{val // digits / 10 ** digits:.{digits}f}%'

values = [random() for _ in range(10000)]

%timeit [floored_percentage(x, 1) for x in values]      # 35.7 ms per loop
%timeit [floored_percentage_jpp(x, 1) for x in values]  # 28.1 ms per loop

1
像这样的内容:
def my_format(num, x):
     return str(num*100)[:4 + (x-1)] + '%'

>>> my_format(.9995, 1)
'99.9%'
>>> my_format(.9995, 2)
'99.95%'
>>> my_format(.9999, 1)
'99.9%'
>>> my_format(0.99987, 2)
'99.98%'

0

有几种方法,也许最简单的是

x = str(10. * 0.9995).split('.')
my_string = '%s.%s%%' % (x[0], x[1][:2])

这将确保您始终将小数点放在正确的位置(例如边缘情况,如1.00000.001


0

在接受的答案基础上进行扩展,同时使用更现代的Python 3.6+ f-string格式化。

def floored_percentage(val, digits):
    val *= 10 ** (digits + 2)
    return f'{floor(val) / 10 ** digits}%)'

如果没有数字(就像我需要的那样),它甚至更简单:

def floored_percentage(val):
    return f"{floor(val*100)}%"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接