¿Cómo puedo formatear un decimal para mostrar siempre 2 lugares decimales?


237

Quiero mostrar:

49 como 49.00

y:

54.9 como 54.90

Independientemente de la longitud del decimal o si hay lugares decimales, me gustaría mostrar un Decimalcon 2 decimales, y me gustaría hacerlo de manera eficiente. El propósito es mostrar valores monetarios.

p.ej, 4898489.00


44
¿Necesitas que sea el mayor tiempo posible? Qué significa eso? Podría agregar ceros a la izquierda hasta que se quede sin memoria, pero sospecho que eso no es lo que quiere ...
Mark Byers

Supongo que podría significar que el OP está usando decimal. Decimal y no está contento con la precisión del contexto decimal que limita la precisión a n dígitos como en "n dígitos de precisión en sentido estricto" (por ejemplo, '123.456' se convierte en decimal ('1.2E + 2 ')) y no "n dígitos en la parte fraccional" (para Decimal (' 123.45 ')) ... Vea mi respuesta para un intento de ser útil con esto. ;-)
Michał Marczyk

1
Sí, son por valores monetarios.
orokusaki

Respuestas:


105

¿Supongo que probablemente estés usando los Decimal()objetos del decimalmódulo? (Si necesita exactamente dos dígitos de precisión más allá del punto decimal con números arbitrariamente grandes, definitivamente debería serlo, y eso es lo que sugiere el título de su pregunta ...)

Si es así, la sección de Preguntas frecuentes sobre decimales de los documentos tiene un par de preguntas / respuestas que pueden ser útiles para usted:

P. En una aplicación de punto fijo con dos lugares decimales, algunas entradas tienen muchos lugares y deben redondearse. Se supone que otros no tienen exceso de dígitos y deben ser validados. ¿Qué métodos deben usarse?

A. El método quantize () se redondea a un número fijo de lugares decimales. Si se establece la trampa Inexact, también es útil para la validación:

>>> TWOPLACES = Decimal(10) ** -2       # same as Decimal('0.01')
>>> # Round to two places
>>> Decimal('3.214').quantize(TWOPLACES)
Decimal('3.21')
>>> # Validate that a number does not exceed two places
>>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Decimal('3.21')
>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Traceback (most recent call last):
   ...
Inexact: None

La siguiente pregunta dice

P. Una vez que tengo entradas válidas de dos lugares, ¿cómo mantengo esa invariante en toda la aplicación?

Si necesita la respuesta a eso (junto con mucha otra información útil), consulte la sección mencionada anteriormente de los documentos . Además, si mantiene su Decimals con dos dígitos de precisión más allá del punto decimal (lo que significa tanta precisión como sea necesaria para mantener todos los dígitos a la izquierda del punto decimal y dos a la derecha y nada más ...), luego convertirlos en cadenas strfuncionará bien:

str(Decimal('10'))
# -> '10'
str(Decimal('10.00'))
# -> '10.00'
str(Decimal('10.000'))
# -> '10.000'

2
Oh, olvidé mencionar la eficiencia en la respuesta ... pero supongo que no soy un experto de todos modos. No veo ninguna razón por la cual sería particularmente ineficiente mantener un número fijo de "dígitos fraccionarios", aunque cualquier operación realizada en los números podría requerir una operación de redondeo en el resultado para alinearlo con los requisitos ... En aras de la eficiencia, esto probablemente debería hacerse con la menor frecuencia posible, como justo antes de la serialización / impresión para el usuario.
Michał Marczyk

517

Debe usar las nuevas especificaciones de formato para definir cómo se debe representar su valor:

>>> from math import pi  # pi ~ 3.141592653589793
>>> '{0:.2f}'.format(pi)
'3.14'

La documentación puede ser un poco obtusa a veces, por lo que recomiendo las siguientes referencias legibles:

Python 3.6 introdujo la interpolación literal de cadenas (también conocida como cadenas f), por lo que ahora puede escribir lo anterior aún más sucinto como:

>>> f'{pi:.2f}'
'3.14'

44
@Droogans: Euh ... formatdevuelve un str, no un float: print type({0:.2f}".format(pi))devuelve <type 'str'>.
BioGeek

Ups Verbo sobrecargado en la palabra return. Por favor, cambia mentalmente eso a prints.
Droogans

20
Si no desea utilizar el marcador de posición numérico:"{:.2f}".format(pi)
Usuario

¿Qué hace el 0:? Supongo que .es parte de la cadena de python
information_interchange

135

La sección Operaciones de formato de cadenas de la documentación de Python contiene la respuesta que está buscando. En breve:

"%0.2f" % (num,)

Algunos ejemplos:

>>> "%0.2f" % 10
'10.00'
>>> "%0.2f" % 1000
'1000.00'
>>> "%0.2f" % 10.1
'10.10'
>>> "%0.2f" % 10.120
'10.12'
>>> "%0.2f" % 10.126
'10.13'

No hay necesidad de 0después de la %, y no hay necesidad de envolver numen un tuple.
user238424

17
En realidad, envolver num en una tupla es una convención de codificación para evitar un error de tipeo en los argumentos durante el formateo de cadenas. No tiene ningún efecto en este caso con una conversión flotante, pero evita un error de tipo inesperado al convertir a cadenas. Considerar r = 1; "%s" % r; r = (1, 2); "%s" % rversus r = 1; "%s" % (r,); r = (1,2 ); "%s" % (r,). Como tal, los estilos de codificación más sofisticados en python usan la tupla incondicional ahora (y Python 3 desaprobó todo el método de formateo de cadenas como propenso a errores).
Travis Bradshaw

Además, como un hombre con antecedentes matemáticos, la notación decimal "desnuda" es fea. El 0 inicial no duele nada y se ve mejor. :)
Travis Bradshaw

3
Estéticamente no es diferente. Lo más importante, el 0 es el valor predeterminado, de todos modos. No hay ningún daño en proporcionar el valor predeterminado si genera un código estéticamente agradable. Es interesante cuántos desarrolladores optan por no (¿no?) Diferenciar entre corrección y estilo. : /
Travis Bradshaw

32

Puede usar el operador de formato de cadena de la siguiente manera:

num = 49
x = "%.2f" % num  # x is now the string "49.00"

No estoy seguro de lo que quiere decir con "eficiente": es casi seguro que este no es el cuello de botella de su aplicación. Si su programa se ejecuta lentamente, perfílelo primero para encontrar los puntos calientes y luego optimícelos.


1
Creo que la variable que se llama 'f' podría confundir a algunas personas. Es mejor llamarlo de otra manera para un ejemplo como Travis a continuación.
Aleck Landgraf

28
>>> print "{:.2f}".format(1.123456)
1.12

Se puede cambiar 2en 2fcualquier número de decimales que desea mostrar.

EDITAR:

De Python3.6, esto se traduce en:

>>> print(f"{1.1234:.2f}")
1.12

19

.format es una forma más legible de manejar el formato variable:

'{:.{prec}f}'.format(26.034, prec=2)


6

si tienes múltiples parámetros puedes usar

 print('some string {0:.2f} & {1:.2f}'.format(1.1234,2.345))
 >>> some string 1.12 & 2.35

3

Si está usando esto para la moneda, y también quiere que el valor esté separado por ,'s', puede usar

$ {:,.f2}.format(currency_value).

p.ej:

currency_value = 1234.50

$ {:,.f2}.format(currency_value) --> $ 1,234.50

Aquí hay un poco de código que escribí hace algún tiempo:

print("> At the end of year " + year_string + " total paid is \t$ {:,.2f}".format(total_paid))

> At the end of year   1  total paid is         $ 43,806.36
> At the end of year   2  total paid is         $ 87,612.72
> At the end of year   3  total paid is         $ 131,419.08
> At the end of year   4  total paid is         $ 175,225.44
> At the end of year   5  total paid is         $ 219,031.80   <-- Note .80 and not .8
> At the end of year   6  total paid is         $ 262,838.16
> At the end of year   7  total paid is         $ 306,644.52
> At the end of year   8  total paid is         $ 350,450.88
> At the end of year   9  total paid is         $ 394,257.24
> At the end of year  10  total paid is         $ 438,063.60   <-- Note .60 and not .6
> At the end of year  11  total paid is         $ 481,869.96
> At the end of year  12  total paid is         $ 525,676.32
> At the end of year  13  total paid is         $ 569,482.68
> At the end of year  14  total paid is         $ 613,289.04
> At the end of year  15  total paid is         $ 657,095.40   <-- Note .40 and not .4  
> At the end of year  16  total paid is         $ 700,901.76
> At the end of year  17  total paid is         $ 744,708.12
> At the end of year  18  total paid is         $ 788,514.48
> At the end of year  19  total paid is         $ 832,320.84
> At the end of year  20  total paid is         $ 876,127.20   <-- Note .20 and not .2

0

El ejemplo de la forma más fácil para mostrarle cómo hacerlo es:

Código:

>>> points = 19.5 >>> total = 22 >>>'Correct answers: {:.2%}'.format(points/total) ``

Salida: respuestas correctas: 88.64%


-6

qué pasa

print round(20.2564567 , 2)    >>>>>>>        20.25


print round(20.2564567 , 4)    >>>>>>>        20.2564
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.