Comment puis-je formater un flottant pour qu'il ne contienne pas de zéros de fin? En d'autres termes, je veux que la chaîne résultante soit aussi courte que possible.
Par exemple:
3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"
3.14 == 3.140
- C'est le même nombre à virgule flottante. D'ailleurs, 3,140000 est le même nombre à virgule flottante. Le zéro n'existe pas en premier lieu.%0.2f
et%0.3f
sont les deux formats requis pour produire les derniers nombres sur la gauche. Utilisez%0.2f
pour produire les deux derniers nombres sur la droite.3.0 -> "3"
est toujours un cas d'utilisation valide.print( '{:,g}'.format( X )
travaillé pour moi pour sortir3
oùX = 6 / 2
et quandX = 5 / 2
j'ai obtenu une sortie de2.5
comme prévu.print("%s"%3.140)
vous donne ce que vous voulez. (J'ai ajouté une réponse ci-dessous ...)Réponses:
Moi, je le ferais
('%f' % x).rstrip('0').rstrip('.')
- garantit le formatage en virgule fixe plutôt que la notation scientifique, etc. etc. Oui, pas aussi lisse et élégant que%g
, mais ça marche (et je ne sais pas comment forcer%g
à ne jamais utiliser la notation scientifique; -).la source
'%.2f' % -0.0001
vous laisser avec-0.00
et finalement-0
.'f' Fixed point. Displays the number as a fixed-point number. The default precision is 6.
Vous devrez utiliser '% 0.7f' dans la solution ci-dessus.'%0.15f'
- dessus est une mauvaise idée, car des choses étranges commencent à se produire.print('In the middle {} and something else'.format('{:f}'.format(a).rstrip('0')))
Vous pouvez utiliser
%g
pour y parvenir:'%g'%(3.140)
ou, pour Python 2.6 ou supérieur:
'{0:g}'.format(3.140)
À partir de la documentation pour
format
:g
causes (entre autres)la source
'{0:...}'.format(value)
quand vous pourriez utiliserformat(value, '...')
? Cela évite d'avoir à analyser le spécificateur de format à partir d'une chaîne de modèle qui est autrement vide.format(v, '2.5f')
pris environ 10% de plus que'{:2.5f}'.format(v)
. Même si ce n'est pas le cas, j'ai tendance à utiliser lestr
formulaire de méthode car lorsque j'ai besoin de le modifier, d'y ajouter des valeurs supplémentaires, etc., il y a moins à changer. Bien sûr, à partir de 3.6, nous avons des chaînes f pour la plupart des cas. :-)f"{var:g}"
oùvar
est une variable flottante.Après avoir examiné les réponses à plusieurs questions similaires, cela semble être la meilleure solution pour moi:
def floatToString(inputValue): return ('%.15f' % inputValue).rstrip('0').rstrip('.')
Mon raisonnement:
%g
ne se débarrasse pas de la notation scientifique.>>> '%g' % 0.000035 '3.5e-05'
15 décimales semblent éviter les comportements étranges et ont beaucoup de précision pour mes besoins.
>>> ('%.15f' % 1.35).rstrip('0').rstrip('.') '1.35' >>> ('%.16f' % 1.35).rstrip('0').rstrip('.') '1.3500000000000001'
J'aurais pu utiliser à la
format(inputValue, '.15f').
place de'%.15f' % inputValue
, mais c'est un peu plus lent (~ 30%).J'aurais pu l'utiliser
Decimal(inputValue).normalize()
, mais cela pose également quelques problèmes. D'une part, c'est BEAUCOUP plus lent (~ 11x). J'ai également trouvé que même s'il a une assez grande précision, il souffre toujours d'une perte de précision lors de l'utilisationnormalize()
.>>> Decimal('0.21000000000000000000000000006').normalize() Decimal('0.2100000000000000000000000001') >>> Decimal('0.21000000000000000000000000006') Decimal('0.21000000000000000000000000006')
Plus important encore, je serais toujours en train de convertir à
Decimal
partir d'unfloat
qui peut vous faire finir avec autre chose que le nombre que vous avez mis là-dedans. Je pense que celaDecimal
fonctionne mieux lorsque l'arithmétique resteDecimal
et que leDecimal
est initialisé avec une chaîne.>>> Decimal(1.35) Decimal('1.350000000000000088817841970012523233890533447265625') >>> Decimal('1.35') Decimal('1.35')
Je suis sûr que le problème de précision de
Decimal.normalize()
peut être ajusté à ce qui est nécessaire en utilisant les paramètres de contexte, mais compte tenu de la vitesse déjà lente et de ne pas avoir besoin d'une précision ridicule et du fait que je serais toujours en train de convertir un flotteur et de perdre de la précision de toute façon, je n'ai Je ne pense pas que cela valait la peine d'être poursuivi.Je ne suis pas préoccupé par le résultat possible "-0" car -0.0 est un nombre à virgule flottante valide et ce serait probablement une occurrence rare de toute façon, mais comme vous avez mentionné que vous souhaitez garder le résultat de la chaîne aussi court que possible, vous pourrait toujours utiliser une condition supplémentaire à très peu de frais de vitesse supplémentaire.
def floatToString(inputValue): result = ('%.15f' % inputValue).rstrip('0').rstrip('.') return '0' if result == '-0' else result
la source
floatToString(12345.6)
renvoie'12345.600000000000364'
par exemple. Réduire le 15%.15f
à un nombre inférieur le résout dans cet exemple, mais cette valeur doit être diminuée de plus en plus à mesure que le nombre augmente. Il pourrait être calculé dynamiquement sur la base du log-base-10 du nombre, mais cela devient rapidement très compliqué.result = ('%15f' % val).rstrip('0').rstrip('.').lstrip(' ')
>>>12345.600000000000364 == 12345.6
True
Pourquoi ne pas essayer l'approche la plus simple et probablement la plus efficace? La méthode normalize () supprime tous les zéros les plus à droite.
from decimal import Decimal print (Decimal('0.001000').normalize()) # Result: 0.001
Travaille dans Python 2 et Python 3 .
-- Mis à jour --
Le seul problème, comme l'a souligné @ BobStein-VisiBone, est que des nombres comme 10, 100, 1000 ... seront affichés en représentation exponentielle. Cela peut être facilement corrigé en utilisant la fonction suivante à la place:
from decimal import Decimal def format_float(f): d = Decimal(str(f)); return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
la source
Decimal('10.0').normalize()
devient'1E+1'
Voici une solution qui a fonctionné pour moi. C'est un mélange de la solution de PolyMesh et de l'utilisation de la nouvelle
.format()
syntaxe .for num in 3, 3., 3.0, 3.1, 3.14, 3.140: print('{0:.2f}'.format(num).rstrip('0').rstrip('.'))
Sortie :
3 3 3 3.1 3.14 3.14
la source
3.141
) car le.2f
est codé en dur.Vous pouvez simplement utiliser format () pour y parvenir:
format(3.140, '.10g')
où 10 est la précision souhaitée.la source
Bien que le formatage soit probablement le moyen le plus pythonique, voici une solution alternative utilisant l'
more_itertools.rstrip
outil.import more_itertools as mit def fmt(num, pred=None): iterable = str(num) predicate = pred if pred is not None else lambda x: x in {".", "0"} return "".join(mit.rstrip(iterable, predicate)) assert fmt(3) == "3" assert fmt(3.) == "3" assert fmt(3.0) == "3" assert fmt(3.1) == "3.1" assert fmt(3.14) == "3.14" assert fmt(3.140) == "3.14" assert fmt(3.14000) == "3.14" assert fmt("3,0", pred=lambda x: x in set(",0")) == "3"
Le nombre est converti en une chaîne, qui est débarrassée des caractères de fin qui satisfont un prédicat. La définition de la fonction
fmt
n'est pas obligatoire, mais elle est utilisée ici pour tester les assertions, qui réussissent toutes. Remarque: il fonctionne sur les entrées de chaîne et accepte les prédicats optionnels.Voir aussi les détails sur cette bibliothèque tierce,
more_itertools
.la source
>>> str(a if a % 1 else int(a))
la source
int(a) if a % 1 else a
?a if a % 1 else int(a)
est correct. La question nécessite une sortie en chaîne, je viens donc d'ajouterstr
a % 1
est la vérité parce qu'elle est non nulle. Je l'ai implicitement et à tort perçu commea % 1 == 0
.L'utilisation du package QuantiPhy est une option. Normalement, QuantiPhy est utilisé lorsque vous travaillez avec des nombres avec des unités et des facteurs d'échelle SI, mais il dispose d'une variété d'options de formatage de nombres intéressantes.
>>> from quantiphy import Quantity >>> cases = '3 3. 3.0 3.1 3.14 3.140 3.14000'.split() >>> for case in cases: ... q = Quantity(case) ... print(f'{case:>7} -> {q:p}') 3 -> 3 3. -> 3 3.0 -> 3 3.1 -> 3.1 3.14 -> 3.14 3.140 -> 3.14 3.14000 -> 3.14
Et il n'utilisera pas la notation électronique dans cette situation:
>>> cases = '3.14e-9 3.14 3.14e9'.split() >>> for case in cases: ... q = Quantity(case) ... print(f'{case:>7} -> {q:,p}') 3.14e-9 -> 0 3.14 -> 3.14 3.14e9 -> 3,140,000,000
Une alternative que vous pourriez préférer est d'utiliser des facteurs d'échelle SI, peut-être avec des unités.
>>> cases = '3e-9 3.14e-9 3 3.14 3e9 3.14e9'.split() >>> for case in cases: ... q = Quantity(case, 'm') ... print(f'{case:>7} -> {q}') 3e-9 -> 3 nm 3.14e-9 -> 3.14 nm 3 -> 3 m 3.14 -> 3.14 m 3e9 -> 3 Gm 3.14e9 -> 3.14 Gm
la source
OP souhaite supprimer les zéros superflus et rendre la chaîne résultante aussi courte que possible.
Je trouve que le formatage exponentiel% g raccourcit la chaîne résultante pour les valeurs très grandes et très petites. Le problème vient des valeurs qui n'ont pas besoin de notation exponentielle, comme 128.0, qui n'est ni très grande ni très petite.
Voici une façon de formater les nombres sous forme de chaînes courtes qui utilise la notation exponentielle% g uniquement lorsque Decimal.normalize crée des chaînes trop longues. Ce n'est peut-être pas la solution la plus rapide (car elle utilise Decimal.normalize)
def floatToString (inputValue, precision = 3): rc = str(Decimal(inputValue).normalize()) if 'E' in rc or len(rc) > 5: rc = '{0:.{1}g}'.format(inputValue, precision) return rc inputs = [128.0, 32768.0, 65536, 65536 * 2, 31.5, 1.000, 10.0] outputs = [floatToString(i) for i in inputs] print(outputs) # ['128', '32768', '65536', '1.31e+05', '31.5', '1', '10']
la source
Pour le flotteur, vous pouvez utiliser ceci:
def format_float(num): return ('%i' if num == int(num) else '%s') % num
Essaye-le:
>>> format_float(1.00000) '1' >>> format_float(1.1234567890000000000) '1.123456789'
Pour décimal, voir la solution ici: https://stackoverflow.com/a/42668598/5917543
la source
Si vous pouvez vivre avec 3. et 3.0 apparaissant comme "3.0", une approche très simple qui supprime à droite les zéros des représentations flottantes:
print("%s"%3.140)
(merci @ellimilial pour avoir signalé les exceptions)
la source
print("%s"%3.0)
fait."{:.5g}".format(x)
J'utilise ceci pour formater les flottants pour suivre les zéros.
la source
Voici la réponse:
import numpy num1 = 3.1400 num2 = 3.000 numpy.format_float_positional(num1, 3, trim='-') numpy.format_float_positional(num2, 3, trim='-')
sortie "3.14" et "3"
trim='-'
supprime à la fois les zéros de fin et la décimale.la source
Utilisez% g avec une largeur suffisamment grande, par exemple '% .99g'. Il imprimera en notation à virgule fixe pour tout nombre raisonnablement grand.
EDIT: ça ne marche pas
>>> '%.99g' % 0.0000001 '9.99999999999999954748111825886258685613938723690807819366455078125e-08'
la source
.99
est la précision, pas la largeur; un peu utile, mais vous ne pouvez pas définir la précision réelle de cette façon (à part la tronquer vous-même).Vous pouvez utiliser
max()
comme ceci:print(max(int(x), x))
la source
x
est négatif.if x < 0: print(min(x), x)
else : print(max(x), x)
Vous pouvez y parvenir de la manière la plus pythonique comme ça:
python3:
"{:0.0f}".format(num)
la source
Gestion de% f et vous devriez mettre
, où: .2f == .00 flotte.
Exemple:
print "Prix:% .2f"% prix [produit]
production:
Prix: 1,50
la source