Python форматирование больших значений
Ниже приведен код для форматирования значения x, которое я использовал.
Примеры того, что это делает:
- Форматирует 7 500 000 в 7,5 млн.
Он форматирует 800 000 в 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 М я хотел бы иметь возможность печатать.55 B
- Вместо 550 B я хотел бы иметь возможность печатать.55 T
- Вместо 550 К я бы хотел печатать.55 М
- Вместо 0,001 я бы хотел печатать 0,001 без нуля.
- Однако 55,5 М, 55,5 В, 55,5 К все еще должны быть напечатаны - не 0,055 М или 0,055 В..
Предложения о том, как выполнить это изменение или улучшить этот фрагмент кода, чтобы иметь более значимые распечатки (которые используются в диаграмме)?
Большое спасибо!
2 ответа
Вероятно, существует более короткий способ генерации строк формата; но они достаточно просты, чтобы просто сопоставить с каждой величиной. Я не совсем понимаю, какое поведение вы хотите с длиной десятичной запятой, но логика для этого должна быть простой.
Так как у вас был метод, я включил это в класс. (Это также позволяет избежать определения 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')
Попробуйте все возможные способы его форматирования и выберите самый короткий по длине с предпочтением более крупных единиц (например, от.55 B до 550 M, поскольку они имеют одинаковую длину).
Что касается удаления начальных нулей, одним из возможных решений является проверка s[:2] == '0.'
и заменить его на '.'