Python格式化大数值

2 投票
2 回答
1927 浏览
提问于 2025-04-16 14:18

下面是我一直在使用的代码,用来格式化一个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')

撰写回答