Python格式化大数值
下面是我一直在使用的代码,用来格式化一个x值。
它的功能示例:
- 把7500000格式化成7.5 M
把800000格式化成800 K
def Formatting(self, x, pos): formats = ((1e-12,'%d%s T','%1.1f T'), (1e-9, '%d%s B','%1.1f B'), (1e-6, '%d%s M','%1.1f M'), (1e-3, '%d%s k','%1.1f K' )) for i, (N, A, B) in enumerate(formats): if abs(x) > (1./N): result = '' x = x * N if abs(x) >= 1000: x, r = divmod(x, 1000) result = ",%03d%s" % (r, result) return A % (x, result) else: return B % (x) elif 1 <= abs(x) < 1e3: return '%1.0f' % (x) elif 0.1 <= abs(x) < 1: return '%1.1f' % (x) elif 0 < abs(x) < 0.1: return '%1.3f' % (x) elif x == 0: return '%1.0f' % (x)
现在,我在努力做以下改进:
- 我希望能把550 M格式化成0.55 B
- 我希望能把550 B格式化成0.55 T
- 我希望能把550 K格式化成0.55 M
- 我希望能把0.001格式化成.001,不要前面的零
- 不过,像55.5 M、55.5 B、55.5 K这样的格式还是要保留,不要变成.055 M或.055 B。
有没有建议可以帮助我修改这段代码,让输出的结果更有意义(比如用于图表)?
非常感谢!
2 个回答
0
试着用各种不同的方式来格式化它,然后选择长度最短的那种,尽量选择更大的单位(比如,.55 B 比 550 M 更好,因为它们的长度是一样的)。
至于去掉前面的零,一个可能的办法是检查一下 s[:2] == '0.'
,如果是的话,就把它替换成 '.'
。
4
可能有更简短的方法来生成格式字符串,但把它们简单地映射到每个大小上也很容易。我不太明白你想要的关于小数点长度的具体行为,不过处理这个逻辑应该不难。
因为你之前用的是一个方法,所以我把它放进了一个类里。(这样做也避免了每次调用函数时都要定义formats
。)
from math import log10
class Formatter(object):
def __init__(self):
self.formats = (('%1.1f', 0),
('%2.1f', 0),
('%1.2f K', 3),
('%1.2f K', 3),
('%2.1f K', 3),
('%1.2f M', 6),
('%1.2f M', 6),
('%2.1f M', 6),
('%1.2f B', 9),
('%1.2f B', 9),
('%2.1f B', 9),
('%1.2f T', 12),
('%1.2f T', 12),
('%2.1f T', 12))
def human_readable(self, x):
if x == 0: return '0'
magnitude = int(log10(abs(x)))
if magnitude > 13: format_str, denominator_mag = '%i T', 12
else: format_str, denominator_mag = self.formats[magnitude]
return (format_str % (x * 1.0 / (10 ** denominator_mag))).lstrip('0')
编辑: 这里有一个不使用查找表的方法:
def human_readable(self, x):
if x == 0: return '0'
magnitude = int(log10(abs(x)))
if magnitude > 13:
format_str = '%i T'
denominator_mag = 12
else:
float_fmt = '%2.1f ' if magnitude % 3 == 1 else '%1.2f '
illion = (magnitude + 1) // 3
format_str = float_fmt + ['', 'K', 'M', 'B', 'T'][illion]
denominator_mag = illion * 3
return (format_str % (x * 1.0 / (10 ** denominator_mag))).lstrip('0')