Comment formater une décimale pour toujours afficher 2 décimales?

237

Je souhaite afficher:

49 comme 49.00

et:

54.9 comme 54.90

Quelle que soit la longueur de la décimale ou s'il y a des décimales, je voudrais afficher un Decimalavec 2 décimales et je voudrais le faire de manière efficace. Le but est d'afficher les valeurs monétaires.

par exemple, 4898489.00

orokusaki
la source
4
Vous en avez besoin pour être le plus longtemps possible? Qu'est-ce que ça veut dire? Vous pouvez ajouter des zéros non significatifs jusqu'à épuisement de la mémoire, mais je soupçonne que ce n'est pas ce que vous voulez ...
Mark Byers
Je suppose que cela pourrait signifier que l'OP utilise decimal.Decimal et n'est pas satisfait de la précision du contexte décimal qui limite la précision à n chiffres comme dans "n chiffres de précision au sens strict" (par exemple, '123.456' devient Decimal ('1.2E + 2 ')) et non pas "n chiffres dans la partie fractionnaire" (pour Decimal (' 123.45 ')) ... Voir ma réponse pour une tentative d'être utile avec cela. ;-)
Michał Marczyk
1
Oui, ils sont pour des valeurs monétaires.
orokusaki du

Réponses:

105

Je suppose que vous utilisez probablement les Decimal()objets dudecimal module? (Si vous avez besoin d'exactement deux chiffres de précision au-delà de la virgule décimale avec des nombres arbitrairement grands, vous devriez certainement l'être, et c'est ce que suggère le titre de votre question ...)

Si tel est le cas, la section FAQ décimale de la documentation contient une paire question / réponse qui peut vous être utile:

Q. Dans une application à virgule fixe avec deux décimales, certaines entrées ont plusieurs places et doivent être arrondies. D'autres ne sont pas censés avoir des chiffres en excès et doivent être validés. Quelles méthodes utiliser?

A. La méthode quantize () arrondit à un nombre fixe de décimales. Si le piège Inexact est défini, il est également utile pour la validation:

>>> 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 question suivante se lit

Q. Une fois que j'ai deux entrées valides, comment puis-je conserver cet invariant tout au long d'une application?

Si vous avez besoin de la réponse à cela (ainsi que de nombreuses autres informations utiles), consultez la section susmentionnée de la documentation . De plus, si vous conservez votre Decimals avec deux chiffres de précision au-delà du point décimal (ce qui signifie autant de précision qu'il est nécessaire pour garder tous les chiffres à gauche du point décimal et deux à droite et pas plus ...), puis les convertir en chaînes avec strfonctionnera bien:

str(Decimal('10'))
# -> '10'
str(Decimal('10.00'))
# -> '10.00'
str(Decimal('10.000'))
# -> '10.000'
Michał Marczyk
la source
2
Oh, j'ai oublié de mentionner l'efficacité dans la réponse ... mais je suppose que je ne suis pas un expert de toute façon. Je ne vois aucune raison pour laquelle il serait particulièrement inefficace de conserver un nombre fixe de "chiffres fractionnaires" - bien que toute opération effectuée sur les nombres puisse nécessiter une opération d'arrondi sur le résultat pour le mettre en conformité avec les exigences ... Pour par souci d'efficacité, cela devrait probablement être fait aussi rarement que possible - comme juste avant la sérialisation / l'impression pour l'utilisateur.
Michał Marczyk
517

Vous devez utiliser les nouvelles spécifications de format pour définir comment votre valeur doit être représentée:

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

La documentation peut parfois être un peu obtuse, donc je recommande les références suivantes, plus faciles à lire:

Python 3.6 a introduit l'interpolation littérale de chaînes (également connue sous le nom de f-strings), vous pouvez donc maintenant écrire ce qui précède encore plus succinct:

>>> f'{pi:.2f}'
'3.14'
BioGeek
la source
4
@Droogans: Euh ... formatretourne un str, pas un float: print type({0:.2f}".format(pi))retourne <type 'str'>.
BioGeek
Oups. Surcharge de verbe sur le mot return. Veuillez modifier mentalement cela par l' printart.
Droogans
20
Si vous ne souhaitez pas utiliser l'espace réservé numérique:"{:.2f}".format(pi)
Utilisateur
Que fait- 0:il? Je suppose que cela .fait partie de la chaîne python
information_interchange
135

La section Opérations de formatage de chaînes de la documentation Python contient la réponse que vous recherchez. En bref:

"%0.2f" % (num,)

Quelques exemples:

>>> "%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
la source
Il n'y a pas besoin de l' 0après %, et pas besoin d'envelopper numdans un tuple.
user238424
17
En fait, encapsuler num dans un tuple est une convention de codage pour éviter une erreur de frappe de canard sur les arguments lors du formatage de la chaîne. Il n'a aucun effet dans ce cas avec une conversion flottante, mais il empêche une erreur de type inattendue lors de la conversion en chaînes. Considérez r = 1; "%s" % r; r = (1, 2); "%s" % rversus r = 1; "%s" % (r,); r = (1,2 ); "%s" % (r,). En tant que tel, la plupart des styles de codage sophistiqués en python utilisent maintenant le tuple inconditionnel (et Python 3 a déconseillé toute la méthode de formatage des chaînes comme sujette aux erreurs).
Travis Bradshaw
En outre, en tant que gars avec une formation en mathématiques, la notation décimale "nue" est moche. Le 0 de tête ne fait rien de mal et semble meilleur. :)
Travis Bradshaw
3
Esthétiquement pas différent. Plus important encore, le 0 est de toute façon la valeur par défaut. Il n'y a absolument aucun mal à fournir la valeur par défaut si elle rend le code esthétiquement agréable. Il est intéressant de voir combien de développeurs choisissent de ne pas (ne peuvent pas?) Faire la différence entre l'exactitude et le style. : /
Travis Bradshaw
32

Vous pouvez utiliser l' opérateur de formatage de chaîne comme suit:

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

Je ne sais pas ce que vous entendez par "efficace" - ce n'est certainement pas le goulot d'étranglement de votre application. Si votre programme s'exécute lentement, profilez-le d'abord pour trouver les points chauds, puis optimisez-les.

Adam Rosenfield
la source
1
Je pense que la variable nommée «f» pourrait dérouter certaines personnes. Mieux vaut l'appeler quelque chose d'autre pour un exemple comme Travis ci-dessous.
Aleck Landgraf
28
>>> print "{:.2f}".format(1.123456)
1.12

Vous pouvez modifier 2en2f un nombre quelconque de points de décimales que vous souhaitez afficher.

ÉDITER:

De Python3.6, cela se traduit par:

>>> print(f"{1.1234:.2f}")
1.12
Aziz Alto
la source
19

.format est un moyen plus lisible de gérer le formatage des variables:

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

En python 3, une façon de faire serait

'{:.2f}'.format(number)
Devin Ersoy
la source
6

si vous avez plusieurs paramètres, vous pouvez utiliser

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

Si vous l'utilisez pour de la monnaie et souhaitez également que la valeur soit séparée par celle que ,vous pouvez utiliser

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

par exemple:

currency_value = 1234.50

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

Voici un peu de code que j'ai écrit il y a quelque temps:

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
la source
0

L'exemple le plus simple pour vous montrer comment procéder est:

Code:

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

Sortie: bonnes réponses: 88,64%

SHARON KERKETTA 1741050
la source
-6

qu'en est-il de

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


print round(20.2564567 , 4)    >>>>>>>        20.2564
Mahmoud Hamdy
la source