Je veux a
être arrondi à 13,95 .
>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999
La round
fonction ne fonctionne pas comme je m'y attendais.
python
floating-point
rounding
precision
ShadowRanger
la source
la source
Réponses:
Vous rencontrez l' ancien problème avec les nombres à virgule flottante que tous les nombres ne peuvent pas être représentés exactement. La ligne de commande vous montre simplement la forme flottante complète de la mémoire.
Avec une représentation en virgule flottante, votre version arrondie est le même nombre. Étant donné que les ordinateurs sont binaires, ils stockent des nombres à virgule flottante sous forme d'entier, puis le divisent par une puissance de deux, de sorte que 13,95 sera représenté de la même manière que 125650429603636838 / (2 ** 53).
Les nombres en double précision ont 53 bits (16 chiffres) de précision et les flottants réguliers ont 24 bits (8 chiffres) de précision. Le type à virgule flottante en Python utilise la double précision pour stocker les valeurs.
Par exemple,
Si vous ne recherchez que deux décimales (pour afficher une valeur monétaire, par exemple), vous avez deux choix:
la source
"%.2f" % round(a,2)
vous pouvez mettre non seulement dans printf, mais aussi dans des choses commestr()
float
) est juste l'approximation disponible la plus proche du nombre décimal (que vous connaissez en tant qu'être humain). Il n'existe aucune valeur binaire (représentable de manière finie) telle que 0,245. Elle n'existe tout simplement pas et mathématiquement ne peut pas exister. La valeur binaire qui est la plus proche de 0,245 est légèrement inférieure à 0,245, elle arrondit donc naturellement. De même, il n'existe pas de 0,225 en binaire, mais la valeur binaire qui est la plus proche de 0,225 est légèrement supérieure à 0,225, donc naturellement elle arrondit.Decimal
, et c'était l'une des solutions présentées dans cette réponse. L'autre consistait à convertir vos quantités en nombres entiers et à utiliser l'arithmétique entière. Ces deux approches sont également apparues dans d'autres réponses et commentaires.Il existe de nouvelles spécifications de format, String Mini-Language Specification :
Vous pouvez faire de même que:
Remarque 1: ce qui précède renvoie une chaîne. Pour obtenir comme flotteur, enveloppez simplement avec
float(...)
:Remarque 2: l' emballage avec
float()
ne change rien:la source
'{0:,.2f}'.format(1333.949999999)
imprimer'1,333.95'
.float()
;float("{0:.2f}".format(13.9499999))
f"Result is {result:.2f}"
La fonction intégrée
round()
fonctionne très bien en Python 2.7 ou version ultérieure.Exemple:
Consultez la documentation .
la source
round(2.16, 1)
donnez2.2
pourquoi python offre juste untruncate
func>>> round(2.675, 2) 2.67
docs.python.org/2/tutorial/floatingpoint.htmlNote The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.
Je pense que l'approche la plus simple consiste à utiliser la
format()
fonction.Par exemple:
Cela produit un nombre flottant sous la forme d'une chaîne arrondie à deux décimales.
la source
Utilisation
au lieu de
Parce que ce dernier peut entraîner des erreurs de sortie lors de la tentative de sortie de plusieurs variables (voir les commentaires).
la source
La plupart des nombres ne peuvent pas être représentés exactement dans des flottants. Si vous voulez arrondir le nombre parce que c'est ce que votre formule mathématique ou votre algorithme requiert, vous devez utiliser arrondir. Si vous souhaitez simplement restreindre l'affichage à une certaine précision, n'utilisez même pas round et formatez-le simplement comme cette chaîne. (Si vous souhaitez l'afficher avec une autre méthode d'arrondi et qu'il y en a des tonnes, vous devez mélanger les deux approches.)
Et enfin, mais peut-être le plus important, si vous voulez des mathématiques exactes, vous ne voulez pas du tout de flottants. L'exemple habituel consiste à gérer l'argent et à stocker les «cents» sous forme d'entier.
la source
Essayez le code ci-dessous:
la source
round
fonction en premier lieu. D'autre part, comme cette solution utilise toujours la virgule flottante, le problème d'origine de l'OP demeure, même pour la version "corrigée" de cette "solution".round
fonction (qui a été utilisée dans la question).round()
ne fonctionne pas comme l'OP mentionné.TLDR;)
Le problème d'arrondi des entrées / sorties a été définitivement résolu par Python 2.7.0 et 3.1 .
Un nombre correctement arrondi peut être converti de façon réversible d'avant en arrière:
str -> float() -> repr() -> float() ...
ouDecimal -> float -> str -> Decimal
Un type décimal n'est plus nécessaire pour le stockage.
(Naturellement, il peut être nécessaire d'arrondir un résultat d'addition ou de soustraction de nombres arrondis pour éliminer les erreurs accumulées du dernier bit. Une arithmétique décimale explicite peut être toujours pratique, mais une conversion en chaîne par
str()
(c'est-à-dire en arrondissant à 12 chiffres valides) ) est généralement assez bonne si aucune précision extrême ou aucun nombre extrême d'opérations arithmétiques successives n'est requis.)Test infini :
Documentation
Voir les notes de publication Python 2.7 - Autres changements de langue, le quatrième paragraphe:
La question connexe
Plus d'informations: Le formatage d'
float
avant Python 2.7 était similaire à l'actuelnumpy.float64
. Les deux types utilisent la même double précision IEEE 754 64 bits avec une mantisse 52 bits. Une grande différence est qu'il est formaté de manière à ce que chaque chiffre soit important; la séquence est sans lacunes et la conversion est réversible. Simplement: si vous avez peut-être un numéro numpy.float64, convertissez-le en float normal afin d'être formaté pour les humains, pas pour les processeurs numériques, sinon rien de plus n'est nécessaire avec Python 2.7+.np.float64.__repr__
est fréquemment formaté avec un nombre décimal excessif afin qu'aucun bit ne puisse être perdu, mais aucun numéro IEEE 754 valide n'existe entre 13,94999999999999999 et 13,950000000000001. Le résultat n'est pas agréable et la conversionrepr(float(number_as_string))
n'est pas réversible avec numpy. D'autre part:float.__repr__
la source
float
(double précision) et normalround
, pas sur numpy.double et sa conversion en chaîne. L'arrondi Python simple ne peut vraiment pas être mieux fait que dans Python 2.7. La plupart des réponses ont été écrites avant la 2.7, mais elles sont obsolètes, même si elles étaient très bonnes à l'origine. C'est la raison de ma réponse.1
, sauf lors d'un "dépassement progressif".a*b
contreb*a
. Merci pour les liens - Nostalgie.Avec Python <3 (par exemple 2.6 ou 2.7), il y a deux façons de le faire.
Mais notez que pour les versions Python supérieures à 3 (par exemple 3.2 ou 3.3), l'option deux est préférée .
Pour plus d'informations sur l'option deux, je suggère ce lien sur le formatage des chaînes de la documentation Python .
Et pour plus d'informations sur la première option, ce lien suffira et contient des informations sur les différents drapeaux .
Référence: convertir un nombre à virgule flottante avec une certaine précision, puis copier dans une chaîne
la source
numvar=12.456
, alors"{:.2f}".format(numvar)
cède12.46
mais"{:2i}".format(numvar)
donne une erreur et je m'attends12
.Vous pouvez modifier le format de sortie:
la source
Personne ici ne semble l'avoir encore mentionné, alors permettez-moi de donner un exemple au format f-string / template-string de Python 3.6, qui je pense est magnifiquement soigné:
Cela fonctionne bien avec des exemples plus longs aussi, avec des opérateurs et sans besoin de parens:
la source
Vous pouvez utiliser l' opérateur de format pour arrondir la valeur jusqu'à 2 décimales en python:
la source
En Python 2.7:
la source
output
a exactement la même valeur quea
, donc vous pourriez aussi bien avoir écritprint a
au lieu deprint output
dans la dernière ligne.13.95
. Mais il en va de mêmeprint a
pour cette valeur particulière dea
Python 2.7, il n'est donc pas vraiment clair quel était le point de l'étape de formatage.a == output
le code que vous montrez? CelaTrue
me donne et je soupçonne que ça le fait aussi pour vous.Le didacticiel Python comporte une annexe intitulée Arithmétique à virgule flottante: problèmes et limites . Lis le. Il explique ce qui se passe et pourquoi Python fait de son mieux. Il a même un exemple qui correspond au vôtre. Permettez-moi de citer un peu:
Une alternative et une solution à vos problèmes serait d'utiliser le
decimal
module.la source
Comme l'a souligné @Matt, Python 3.6 fournit des chaînes f , et ils peuvent également utiliser des paramètres imbriqués :
qui affichera
result: 2.35
la source
Il fait exactement ce que vous lui avez dit de faire et fonctionne correctement. En savoir plus sur la confusion en virgule flottante et peut-être essayer des objets décimaux à la place.
la source
Utilisez une combinaison d'objet Decimal et de méthode round ().
la source
Pour fixer la virgule flottante dans les langages de type dynamique tels que Python et JavaScript, j'utilise cette technique
Vous pouvez également utiliser Decimal comme suit:
la source
getcontext().prec = 6
fonctionne pour la portée de la fonction ou pour tous les endroits?Résultats:
la source
la source
Qu'en est-il d'une fonction lambda comme celle-ci:
De cette façon, vous pouvez simplement faire:
et obtenir
la source
C'est simple comme 1,2,3:
utiliser décimal module pour une arithmétique décimale décimale à virgule flottante correctement arrondie:
d = décimal (10000000.0000009)
pour arrondir:
sera résultats avec
Decimal('10000000.00')
OU
PS: critique des autres: le formatage n'est pas arrondi.
la source
Pour arrondir un nombre à une résolution, la meilleure façon est la suivante, qui peut fonctionner avec n'importe quelle résolution (0,01 pour deux décimales ou même d'autres étapes):
la source
numpy.round
exactitude / précision. Il faut donc le définir comme entier avant multiplication avec résolution. J'ai mis à jour le code. Merci pour ça!numpy.float64
résultat de np.round enfloat
ou simplement d'utiliserround(value, 2)
. Aucun numéro IEEE 754 valide n'existe entre le 13.94999999999999999 (= 1395 / 100.) et le 3.950000000000001 (= 1395 * .01). Pourquoi pensez-vous que votre méthode est la meilleure? La valeur d'origine 13.949999999999999289 (= valeur = round (valeur, 2)) est encore plus exacte que votre 13.950000000000001717 (imprimée par np.float96). Plus d'informations également pour numpy sont maintenant ajoutées à ma réponse que vous avez probablement downvoted par erreur. Il ne s'agissait pas de numpy à l'origine.int
vous, vous pouvez également utiliser l'float
exemple @szeitlin. Merci pour votre commentaire supplémentaire. (Désolé mais je ne vous ai pas downvote)lambda x, n: int (x * 10 n + .5) / 10 n travaille pour moi depuis de nombreuses années dans de nombreuses langues.
la source
La méthode que j'utilise est celle du découpage de chaîne. C'est relativement rapide et simple.
Tout d'abord, convertissez le flotteur en chaîne, puis choisissez la longueur que vous souhaitez qu'il soit.
Dans la seule ligne ci-dessus, nous avons converti la valeur en chaîne, puis conservé la chaîne uniquement dans ses quatre premiers chiffres ou caractères (inclus).
J'espère que cela pourra aider!
la source