¿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

orokusaki
fuente
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'
Michał Marczyk
fuente
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'
BioGeek
fuente
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'
Travis Bradshaw
fuente
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.

Adam Rosenfield
fuente
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
Aziz Alto
fuente
19

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

'{:.{prec}f}'.format(26.034, prec=2)
Mayank Patel
fuente
18

En Python 3, una forma de hacerlo sería

'{:.2f}'.format(number)
Devin Ersoy
fuente
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
sushmit
fuente
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
3kstc
fuente
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%

SHARON KERKETTA 1741050
fuente
-6

qué pasa

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


print round(20.2564567 , 4)    >>>>>>>        20.2564
Mahmoud Hamdy
fuente