通过使用嵌套格式参数对str.format的单个调用,您可以执行所有操作:def format_float(value, ndigits=4):
j = min(i-1 for i in range(ndigits+1) if value >= 10 ** (ndigits - i))
return '{:.0{num_digits}f}'.format(value, num_digits=max(0,j))
{{cd2}的最小值应该大于cd2}。如果指定0的小数位数,则该数字四舍五入为整数,因此输出是正确的。在
示例用法:
^{pr2}$
但是,对于小输入,这将失败:In [68]: format_float(0.0001, 4)
-
ValueError Traceback (most recent call last)
in ()
> 1 format_float(0.0001, 4)
in format_float(value, ndigits)
1 def format_float(value, ndigits=4):
> 2 j = min(i-1 for i in range(ndigits+1) if value >= 10 ** (ndigits - i))
3 return '{:.0{num_digits}f}'.format(value, num_digits=max(0,j))
ValueError: min() arg is an empty sequence
为了得到你想要的小数字,我们必须做一些更复杂的事情,检查小数位数。在这种情况下,只需将数字转换为字符串并删除不需要的位置会更简单。在
尝试可以是:def format_float(value, ndigits=4):
try:
j = min(i-1 for i in range(ndigits+1) if value >= 10 ** (ndigits - i))
return '{:.0{num_digits}f}'.format(value, num_digits=max(0,j))
except ValueError:
s = '{:.20f}'.format(value).rstrip('0')
_, dec_part = s.split('.')
if len(dec_part) > ndigits:
if set(dec_part[:ndigits]) != {'0'}:
dec_part = dec_part[:ndigits]
else:
for i, char in enumerate(dec_part):
if char != '0':
dec_part = dec_part[:i+1]
break
if not dec_part:
# should happen only if the input is 0.0
return '0'
else:
return '{}.{}'.format(0, dec_part)
这似乎适用于问题中提供的输入:In [81]: inputs = [11111.1, 111.11, 11.111, 1.1111, 0.00111, 0.000011]
In [82]: for inp in inputs:
...: print('Input = {} output = {}'.format(inp, format_float(inp, 4)))
Input = 11111.1 output = 11111
Input = 111.11 output = 111.1
Input = 11.111 output = 11.11
Input = 1.1111 output = 1.111
Input = 0.00111 output = 0.0011
Input = 1.1e-05 output = 0.00001
这不处理负数,但很容易检查负数并使用绝对值:def format_float(value, ndigits):
sign = ''
if value < 0:
value = abs(value)
sign = '-'
if value >= 1:
j = min(i-1 for i in range(ndigits+1) if value >= 10 ** (ndigits - i))
return '{}{:.0{num_digits}f}'.format(sign, value, num_digits=max(0,j))
s = '{:.17f}'.format(value).rstrip('0')
_, dec_part = s.split('.')
if not dec_part:
# Happens only with 0.0
return '0'
if len(dec_part) < ndigits or set(dec_part[:ndigits]) != {'0'}:
# truncate the decimal representation
dec_part = dec_part.ljust(ndigits, '0')[:ndigits]
elif len(dec_part) > ndigits:
# too small. Just find the first decimal place
for i, char in enumerate(dec_part):
if char != '0':
dec_part = dec_part[:i+1]
break
return '{}{}.{}'.format(sign, 0, dec_part)