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]
static_rtti
la source

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.

PlasmaBinturong
la source
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é.

Esteban Küber
la source
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]

Robert Rossney
la source
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]
Pablo Santa Cruz
la source
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 
dalloliogm
la source
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]
fortran
la source
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
Chikipowpow
la source
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]
Markus Dutschke
la source
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

Echo dit réintégrer Monica
la source
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
Jed Smith
la source
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]
Rainald62
la source
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')
ifmihai
la source
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)
u0b34a0f6ae
la source
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 ...

kitsu.eb
la source
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<--
x0s
la source
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)

Emile
la source
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)
PTBNL
la source
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)
Romerito
la source