Python formateando grandes valores

A continuación se muestra el código para formatear un valor x que he estado usando.

Ejemplos de lo que hace:

  • Formatea 7,500,000 en 7.5 M
  • Formatea 800,000 en 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) 

Ahora, he estado luchando para hacer las siguientes mejoras:

  • En lugar de 550 M, me gustaría poder imprimir .55 B
  • En lugar de 550 B, me gustaría poder imprimir .55 T
  • En lugar de 550 K, me gustaría poder imprimir .55 M
  • En lugar de 0.001, me gustaría poder imprimir .001 sin el cero
  • Sin embargo, 55.5 M, 55.5 B, 55.5 K aún deben imprimirse, no .055 M, o .055 B ..

¿Sugerencias sobre cómo realizar este cambio o mejorar esta pieza de código para tener impresiones más significativas (que se usan en una tabla)?

¡Muchas gracias!

Probablemente hay una forma más corta de generar las cadenas de formato; pero son bastante fáciles de asignar a cada magnitud. No entiendo completamente el comportamiento que desea con la longitud del punto decimal w / r / t, pero la lógica para eso debería ser fácil.

Como lo que tenías era un método, lo incorporé a una clase. (Esto también evita la definición de formats cada vez que se llama a la función).

 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') 

Edición : Aquí hay una que no usa una tabla de búsqueda:

 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') 

Pruebe todas las diferentes formas posibles de formatearlo y elija la más corta longitudinalmente, dando preferencia a las unidades más grandes (por ejemplo, prefiera .55 B a 550 M, ya que tienen la misma longitud).

En cuanto a eliminar los ceros a la izquierda, una solución posible es verificar si s[:2] == '0.' y reemplazándolo con '.'