Python格式化大值


问题内容

下面是格式化我一直在使用的x值的代码。

其功能示例:

  • 它将7,500,000格式化为7.5 M
  • 它将800,000格式化为800 K It
    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)
    

现在,我一直在努力进行以下改进:

  • 我希望能够打印.55 B,而不是550 M
  • 而不是550 B,我希望能够打印.55 T
  • 我希望能够打印.55 M,而不是550 K
  • 我希望可以不使用零打印.001,而不是0.001。
  • 但是,仍应打印55.5 M,55.5 B,55.5 K,而不是.055 M或.055B。

关于如何执行此更改或改进这段代码以具有更多含义的打印输出(在图表中使用)的建议?

非常感谢你!


问题答案:

生成格式字符串的方法可能更短;但是它们很容易就可以映射到每个量级。我不完全了解您想要w / r / t小数点长度的行为,但是这样做的逻辑应该很简单。

由于您拥有的是一种方法,因此我将其合并到一个类中。(这也避免了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')