根据整数和小数部分的位数来设置十进制格式的最简单方法是什么?让我们说用户选择看4个数字,然后我有这个测试用例:
[('11111.1', '11111'), # Integer part has >= 4 digits keep only integer part
('111.11', '111.1'), # Integer part has < 4 digits keep total 4 digits
('11.111', '11.11'),
('1.1111', '1.111'),
('0.00111', '0.0011'), # Integer part has no digits keep 4 decimal part digits
('0.000011', '0.00001')] # First not zero digit place is > 4 keep first digit
解决方案应该允许选择要查看的位数。
更新目前我使用的解决方案不允许选择要查看的位数:
if value >= 1000:
return '%d' % int(round(value, 0))
elif value >= 100:
return '%.01f' % value
elif value >= 10:
return '%.02f' % value
...
答案 0 :(得分:1)
您只需使用嵌套格式参数调用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))
这个想法是小数位数应该等于最小i
,使得该值大于10 ^ (ndigits -i)
。如果指定0
的小数位数,则数字四舍五入为整数,因此输出正确。
示例用法:
In [66]: inputs = [11111.1, 111.11, 11.111, 1.1111]
In [67]: 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
然而,输入较小时会失败:
In [68]: format_float(0.0001, 4)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-68-68e3461a51e5> in <module>()
----> 1 format_float(0.0001, 4)
<ipython-input-64-d4485ac4e1c9> 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)
答案 1 :(得分:0)
在对不同列表进行排序之前,您需要获得十进制级别
import math
def get_decimal_level(number):
return int(round(math.log(number, 10), 10)) + 1
测试
>>> get_decimal_level(99999)
5
>>> get_decimal_level(100000)
6
让它发挥作用
from collections import defaultdict
def group_list_on_levels(numbers):
group_numbers = defaultdict(list)
for number in numbers:
group_numbers[get_decimal_level(number)].append(number)
levels = group_numbers.keys()
levels.sort(reverse=True)
return [group_numbers[key] for level in levels]
numbers = [31243,543543.654,543543,0.001]
final_list = group_list_on_levels(numbers)
print(final_list) # Check your answer
在控制台中我得到了
[[543543.654, 543543], [31243], [0.001]]
P.S。并且没有十进制字符串转换
答案 2 :(得分:-1)
看不到简单的一两行解决方案。下面的代码解决了您的问题。
def formatNumber(a, DIGITS_TO_KEEP):
p = a.index('.')
if p >= DIGITS_TO_KEEP:
return a[:p]
else:
q = 0
while q+1 < len(a) and (a[q]=='.' or a[q]=='0'):
q += 1
return a[:max(DIGITS_TO_KEEP, q)+1]
for case in ['11111.1', '111.11', '11.111', '1.1111', '0.00111', '0.000011']:
print case, ":", formatNumber(case, 4)