Jolie impression facile de flotteurs en python?


93

J'ai une liste de flotteurs. Si je le fais simplement print, cela se présente comme ceci:

[9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

Je pourrais utiliser print "%.2f", ce qui nécessiterait une forboucle pour parcourir la liste, mais cela ne fonctionnerait pas pour des structures de données plus complexes. J'aimerais quelque chose comme (j'invente complètement ça)

>>> import print_options
>>> print_options.set_float_precision(2)
>>> print [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
[9.0, 0.05, 0.03, 0.01, 0.06, 0.08]

Réponses:


24

C'est une vieille question mais j'ajouterais quelque chose de potentiellement utile:

Je sais que vous avez écrit votre exemple dans des listes Python brutes, mais si vous décidez d'utiliser des numpytableaux à la place (ce qui serait parfaitement légitime dans votre exemple, car vous semblez avoir affaire à des tableaux de nombres), il y a (presque exactement) cette commande vous dit que tu as inventé:

import numpy as np
np.set_printoptions(precision=2)

Ou encore mieux dans votre cas si vous voulez toujours voir toutes les décimales de nombres vraiment précis, mais supprimez les zéros de fin par exemple, utilisez la chaîne de mise en forme %g:

np.set_printoptions(formatter={"float_kind": lambda x: "%g" % x})

Pour imprimer une seule fois et ne pas changer le comportement global, utilisez np.array2stringles mêmes arguments que ci-dessus.


102

Comme personne ne l'a ajouté, il convient de noter qu'à partir de Python 2.6+, la manière recommandée de formater une chaîne est avec format, pour se préparer pour Python 3+.

print ["{0:0.2f}".format(i) for i in a]

La nouvelle syntaxe de formatage de chaîne n'est pas difficile à utiliser, et pourtant elle est assez puissante.

Je pensais que ça pprintpouvait avoir quelque chose, mais je n'ai rien trouvé.


1
C'est celui que j'ai utilisé mais j'ai ajouté .replace("'", "")pour me débarrasser de ces virgules. str(["{0:0.2f}".format(i) for i in a]).replace("'", "")
Steinarr Hrafn Höskuldsson

Cela produira une liste de chaînes. Dans la sortie imprimée, chaque élément est ''entouré. Par exemple, pour a=[0.2222, 0.3333], il produira ['0.22', '0.33'].
jdhao

Pour supprimer le sommet et les virgules, vous devez utiliser' '.join([{0:0.2f}".format(i) for i in a])
Neb

78

Une solution plus permanente consiste à sous float- classer :

>>> class prettyfloat(float):
    def __repr__(self):
        return "%0.2f" % self

>>> x
[1.290192, 3.0002, 22.119199999999999, 3.4110999999999998]
>>> x = map(prettyfloat, x)
>>> x
[1.29, 3.00, 22.12, 3.41]
>>> y = x[2]
>>> y
22.12

Le problème avec le sous float- classement est qu'il rompt le code qui recherche explicitement le type d'une variable. Mais pour autant que je sache, c'est le seul problème. Et un simple x = map(float, x)annule la conversion en prettyfloat.

Tragiquement, vous ne pouvez pas simplement faire un patch de singe float.__repr__, car c'est floatimmuable.

Si vous ne voulez pas de sous float- classe , mais que la définition d'une fonction ne vous dérange pas, map(f, x)c'est beaucoup plus concis que[f(n) for n in x]


J'aurais pensé qu'il y avait une solution plus simple, mais votre réponse est clairement la meilleure, puisque vous êtes à peu près le seul à répondre à ma question.
static_rtti

4
Il est le seul à répondre à votre question - éditée -. Ne pas dénigrer le répondeur, mais vous ne pouvez pas clarifier une question, puis alléger le reste des répondants en fonction des informations avec lesquelles nous travaillions.
Jed Smith

1
Ma question initiale mentionnait que je considérais qu'une boucle for n'était pas une bonne solution (pour moi, la compréhension d'une liste est la même, mais je suis d'accord que ce n'était pas clair). J'essaierai d'être plus clair la prochaine fois.
static_rtti

2
[f (n) pour n dans x] est beaucoup plus pythonique que map (f, x).
Robert T.McGibbon

2
Je ne suis pas nécessairement en faveur de la sous-classification de float, mais je ne pense pas que la vérification de type soit un argument valide. Lors de la vérification des types, isinstancedoit être utilisé, pas l'égalité de type(). Quand cela est fait correctement, une sous-classe de float sera toujours comptée comme float.
zondo le

37

Tu peux faire:

a = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
print ["%0.2f" % i for i in a]

3
Cela affichera ['9,00', '0,05', '0,03', '0,01', '0,06', '0,08'] - avec des guillemets, ce que vous ne voulez généralement pas (je préfère avoir une liste valide de flottants imprimé)
Emile

23

Notez que vous pouvez également multiplier une chaîne comme "% .2f" (exemple: "% .2f" * 10).

>>> print "%.2f "*len(yourlist) % tuple(yourlist)
2.00 33.00 4.42 0.31 

3
très élégant! Je l'aime
Nathan Fellman

2
-1 hack terrible. Joindre des morceaux de chaînes formatés, pas l'inverse s'il vous plaît
u0b34a0f6ae

1
donc kaizer.se, proposez-vous "" .join (["%. 2f"% x pour x dans votre liste]). Je dois faire ce genre de construction en python.
Gregg Lind

oui, je propose " ".join("%.2f" % x for x in yourlist)car séparer la chaîne de format et les valeurs d'interpolation est bien pire que d'utiliser un idiome Python laid.
u0b34a0f6ae

C'est de la curiosité. Pourquoi le tuple fonctionne-t-il alors que la liste échoue? Sans "tuple", cela fait une erreur. Pourquoi?
Joonho Park le

8
print "[%s]"%", ".join(map(str,yourlist))

Cela évitera les erreurs d'arrondi dans la représentation binaire lors de l'impression, sans introduire de contrainte de précision fixe (comme le formatage avec "%.2f"):

[9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.0793303]

7
l = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

Python 2:

print ', '.join('{:0.2f}'.format(i) for i in l)

Python 3:

print(', '.join('{:0.2f}'.format(i) for i in l))

Production:

9.00, 0.05, 0.03, 0.01, 0.06, 0.08

Je ne sais pas pourquoi ce n'est pas plus élevé. Une solution qui ne repose pas sur des bibliothèques tierces!
Fl.pf.

7

L'option la plus simple devrait être d'utiliser une routine d'arrondi:

import numpy as np
x=[9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

print('standard:')
print(x)
print("\nhuman readable:")
print(np.around(x,decimals=2))

Cela produit la sortie:

standard:
[9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.0793303]

human readable:
[ 9.    0.05  0.03  0.01  0.06  0.08]

c'est une excellente réponse
jjz

4

Je crois que Python 3.1 les imprimera mieux par défaut, sans aucun changement de code. Mais cela ne sert à rien si vous utilisez des extensions qui n'ont pas été mises à jour pour fonctionner avec Python 3.1


1
Python 3.1 imprimera la représentation décimale la plus courte qui correspond à cette valeur flottante. Par exemple: >>> a, b = float (1.1), float (1.1000000000000001) >>> a 1.1000000000000001 >>> b 1.1000000000000001 >>> print (a, b) 1.1 1.1
Matt Boehm

4

Les comps de liste sont votre ami.

print ", ".join("%.2f" % f for f in list_o_numbers)

Essayez-le:

>>> nums = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999]
>>> print ", ".join("%.2f" % f for f in nums)
9.00, 0.05, 0.03, 0.01

5
Une expression de générateur serait encore meilleure: "," .join ("%. 2f"% f pour f dans list_o_numbers)
efotinis

@efotinis Je n'ai pas encore ajouté ceux-ci à mon répertoire, mais vous avez raison - c'est plutôt sexy.
Jed Smith

1
@Jed: Veuillez lire la FAQ, section "D'autres personnes peuvent éditer mon contenu?!": Stackoverflow.com/faq . Toutes les modifications ne sont pas bonnes, mais celle-ci était une véritable amélioration. Peut-être pouvez-vous énumérer les deux techniques dans votre réponse et ajouter une note sur la différence?
Stephan202

4

Pour contrôler le nombre de chiffres significatifs , utilisez le spécificateur de format% g.

Appelons la solution d'Emile prettylist2f. Voici la version modifiée:

prettylist2g = lambda l : '[%s]' % ', '.join("%.2g" % x for x in l)

Usage:

>>> c_e_alpha_eps0 = [299792458., 2.718281828, 0.00729735, 8.8541878e-12]
>>> print(prettylist2f(c_e_alpha_eps0)) # [299792458.00, 2.72, 0.01, 0.00]
>>> print(prettylist2g(c_e_alpha_eps0)) # [3e+08, 2.7, 0.0073, 8.9e-12]

Si vous voulez de la flexibilité dans le nombre de chiffres significatifs, utilisez plutôt le formatage de chaîne F :

prettyflexlist = lambda p, l : '[%s]' % ', '.join(f"{x:.{p}}" for x in l)
print(prettyflexlist(3,c_e_alpha_eps0)) # [3e+08, 2.72, 0.0073, 8.85e-12]

3

Vous pourriez utiliser des pandas.

Voici un exemple avec une liste:

In: import pandas as P
In: P.set_option('display.precision',3)
In: L = [3.4534534, 2.1232131, 6.231212, 6.3423423, 9.342342423]
In: P.Series(data=L)
Out: 
0    3.45
1    2.12
2    6.23
3    6.34
4    9.34
dtype: float64

Si vous avez un dict d et que vous voulez ses clés sous forme de lignes:

In: d
Out: {1: 0.453523, 2: 2.35423234234, 3: 3.423432432, 4: 4.132312312}

In: P.DataFrame(index=d.keys(), data=d.values())
Out:  
    0
1   0.45
2   2.35
3   3.42
4   4.13

Et une autre façon de donner un dict à un DataFrame:

P.DataFrame.from_dict(d, orient='index')

2

Tout d'abord, les éléments d'une collection impriment leur repr. vous devriez vous renseigner sur __repr__et __str__.

C'est la différence entre print repr (1.1) et print 1.1. Joignons toutes ces chaînes au lieu des représentations:

numbers = [9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.07933]
print "repr:", " ".join(repr(n) for n in numbers)
print "str:", " ".join(str(n) for n in numbers)

REMARQUE: Dans Python 2.7, pour cet exemple, les résultats de la ligne "repr" et de la ligne "str" ​​sont identiques.
ToolmakerSteve

2

Je viens de rencontrer ce problème en essayant d'utiliser pprint pour générer une liste de tuples de flottants. Les compréhensions imbriquées peuvent être une mauvaise idée, mais voici ce que j'ai fait:

tups = [
        (12.0, 9.75, 23.54),
        (12.5, 2.6, 13.85),
        (14.77, 3.56, 23.23),
        (12.0, 5.5, 23.5)
       ]
pprint([['{0:0.02f}'.format(num) for num in tup] for tup in tups])

J'ai utilisé des expressions de générateur au début, mais pprint vient de reprendre le générateur ...


2

Depuis Python 3.6, vous pouvez utiliser des chaînes f:

list_ = [9.0, 0.052999999999999999, 
         0.032575399999999997, 0.010892799999999999, 
         0.055702500000000002, 0.079330300000000006]

print(*[f"{element:.2f}" for element in list_])
#9.00 0.05 0.03 0.01 0.06 0.08

Vous pouvez utiliser les paramètres d'impression tout en gardant le code très lisible:

print(*[f"{element:.2f}" for element in list_], sep='|', end='<--')
#9.00|0.05|0.03|0.01|0.06|0.08<--

1

J'ai eu ce problème, mais aucune des solutions ici n'a fait exactement ce que je voulais (je veux que la sortie imprimée soit une expression python valide), alors que diriez-vous de ceci:

prettylist = lambda l : '[%s]' % ', '.join("%.2f" % f for f in l)

Usage:

>>> ugly = [9.0, 0.052999999999999999, 0.032575399999999997,
            0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
>>> prettylist = lambda l : '[%s]' % ', '.join("%.2f" % f for f in l)
>>> print prettylist(ugly)
[9.00, 0.05, 0.03, 0.01, 0.06, 0.08]

(Je sais que .format () est censé être la solution la plus standard, mais je trouve cela plus lisible)


0

Je suis d'accord avec le commentaire de SilentGhost, la boucle for n'est pas si mal. Vous pouvez réaliser ce que vous voulez avec:

l = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
for x in l: print "%0.2f" % (x)

3
Bien que les boucles for ne soient pas laides, cette utilisation n'est pas terriblement pythonique.
Jed Smith

-1

Le code ci-dessous fonctionne bien pour moi.

list = map (lambda x: float('%0.2f' % x), list)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.