round () en Python ne semble pas arrondir correctement


Answers

Le formatage fonctionne correctement même sans devoir arrondir:

"%.1f" % n
Question

La documentation de la fonction round() indique que vous lui passez un nombre et les positions après la virgule décimale. Ainsi, il devrait faire ceci:

n = 5.59
round(n, 1) # 5.6

Mais, en réalité, la bonne vieille bizarrerie à virgule flottante s'insinue et vous obtenez:

5.5999999999999996

Pour les besoins de l'interface utilisateur, j'ai besoin d'afficher 5.6 . J'ai fouillé autour d'Internet et j'ai trouvé de la documentation que cela dépendait de mon implémentation de Python. Malheureusement, cela se produit à la fois sur ma machine de développement Windows et sur chaque serveur Linux que j'ai essayé. Voir ici aussi .

À court de créer ma propre bibliothèque ronde, y a-t-il un moyen de contourner cela?




Fonctionne parfaitement

format(5.59, '.1f') # to display
float(format(5.59, '.1f')) #to round



Voici où je vois un échec rond. Et si vous vouliez arrondir ces 2 chiffres à une décimale? 23.45 23.55 Mon éducation était que d'arrondir ceux-ci vous devriez obtenir: 23.4 23.6 la "règle" étant que vous devriez arrondir si le nombre précédent était impair, pas arrondi vers le haut si le nombre précédent était pair. La fonction round dans python tronque simplement le 5.




Jetez un oeil au module Décimal

Decimal "est basé sur un modèle à virgule flottante qui a été conçu en pensant aux gens, et qui a nécessairement un principe directeur primordial - les ordinateurs doivent fournir une arithmétique qui fonctionne de la même manière que l'arithmétique que les gens apprennent à l'école." la spécification arithmétique décimale.

et

Les nombres décimaux peuvent être représentés exactement. En revanche, les nombres comme 1.1 et 2.2 n'ont pas de représentation exacte en virgule flottante binaire. Les utilisateurs finaux ne s'attendent généralement pas à ce que 1.1 + 2.2 s'affiche sous la forme 3.3000000000000003 comme c'est le cas avec le virgule flottante binaire.

Decimal fournit le type d'opérations qui facilitent l'écriture d'applications nécessitant des opérations à virgule flottante et qui doit également présenter ces résultats dans un format lisible par l'homme, par exemple, la comptabilité.




Le problème est seulement quand le dernier chiffre est 5. Par exemple. 0.045 est stocké en interne comme 0.044999999999999 ... Vous pouvez simplement incrémenter le dernier chiffre à 6 et arrondir. Cela vous donnera les résultats souhaités.

import re


def custom_round(num, precision):
    # Get the type of given number
    type_num = type(num)
    # If the given type is not a valid number type, raise TypeError
    if type_num not in [int, float, Decimal]:
        raise TypeError("type {} doesn't define __round__ method".format(type_num.__name__))
    # If passed number is int, there is no rounding off.
    if type_num == int:
        return num
    # Convert number to string.
    str_num = str(num)
    # Get the precision of the given number.
    num_precision = len(str_num.split('.')[1])
    # Rounding off is done only if number precision is
    # greater than requested precision
    if num_precision <= precision:
        return num
    # Replace the last '5' with 6 so that rounding off returns desired results
    if str_num[-1] == '5':
        str_num = re.sub('5$', '6', str_num)
    return round(type_num(str_num), precision)



Vous pouvez passer le type de données à un entier:

>>> n = 5.59
>>> int(n * 10) / 10.0
5.5
>>> int(n * 10 + 0.5) 
56

Puis affichez le numéro en insérant le séparateur décimal de l'environnement local.

Cependant, la réponse de Jimmy est meilleure.




round(5.59, 1) fonctionne bien. Le problème est que 5.6 ne peut pas être représenté exactement en virgule flottante binaire.

>>> 5.6
5.5999999999999996
>>> 

Comme le dit Vinko, vous pouvez utiliser la mise en forme de chaîne pour arrondir l'affichage.

Python a un module pour l'arithmétique décimale si vous en avez besoin.




printf le meunier.

print '%.1f' % 5.59  # returns 5.6





Links