Question

python comparaison décimale

>>> from decimal import Decimal
>>> Decimal('1.0') > 2.0
True

Je me attendais à convertir correctement 2.0, mais après avoir lu à travers PEP 327 Je comprends qu'il y avait une raison pour ne pas convertir implictly flotteur décimal, mais ne doit pas, dans ce cas il devrait augmenter TypeError comme dans ce cas

>>> Decimal('1.0') + 2.0
Traceback (most recent call last):
  File "<string>", line 1, in <string>
TypeError: unsupported operand type(s) for +: 'Decimal' and 'float'

fait donc tout autre opérateur / -% // etc

donc mes questions sont

  1. est-ce bon comportement? (Ne pas soulever exception cmp)
  2. Et si je tire ma propre classe et à droite un convertisseur de flotteur essentiellement Decimal (repr (float_value)), sont Y at-il des mises en garde? mon cas d'utilisation implique que la comparaison des prix

Détails du système: Python sur Ubuntu 8.04.1 2.5.2

Était-ce utile?

La solution

Re 1, il est en effet le comportement que nous avons conçu -. Bien ou mal car il peut être (! Désolé si ce Trips est votre cas d'utilisation, mais nous avons essayé d'être général)

Plus précisément, il est depuis longtemps le cas que chaque objet Python pourrait faire l'objet à la comparaison des inégalités avec tous les autres - objets de types qui ne sont pas vraiment comparables obtenir arbitrairement comparés (toujours dans une course donnée, pas nécessairement à travers court); principal cas d'utilisation a été trier une liste hétérogène à des éléments de groupe en elle par type.

Une exception a été introduite pour les nombres complexes seulement, ce qui les rend non comparables à quoi que ce soit - mais il y avait encore de nombreuses années, quand nous étions à l'occasion cavalière à rompre tout à fait bon code utilisateur. Aujourd'hui, nous sommes beaucoup plus strictes sur la compatibilité ascendante dans une version majeure (par exemple le long de la ligne de 2.*, et séparément le long d'une 3.*, bien que les incompatibilités sont autorisés entre 2 et 3 - en fait c'est le point entier de ayant une série key=lambda x: str(type(x)), nous laisser fixer des décisions de conception passées même de manière incompatible).

Les comparaisons arbitraires se sont avérés être plus mal que ce qu'ils valent la peine, ce qui provoque la confusion des utilisateurs; et le groupement par type peut maintenant être obtenu facilement par exemple avec un argument sort à '%.2f' % x; donc en Python 3 comparaisons entre les objets de différents types, à moins que les objets eux-mêmes autorisent explicitement dans les méthodes de comparaison, soulève une exception:

>>> decimal.Decimal('2.0') > 1.2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: Decimal() > float()

En d'autres termes, en Python 3 ce se comporte exactement comme vous pensez qu'elle devrait; mais en Python 2, il n'a pas (et ne sera, en tout Python repr(x)).

Re 2, vous serez très bien - mais, regardez gmpy pour ce Je l'espère est un moyen intéressant de convertir en double aux fractions de précision infinie à travers les arbres Farey. Si les prix que vous avez affaire sont précis à plus de cents, plutôt que d'utiliser <=> <=> -)

Au lieu d'une sous-classe de Decimal, j'utiliser une fonction d'usine comme

def to_decimal(float_price):
    return decimal.Decimal('%.2f' % float_price)

car, une fois produit, le résultat est Décimal une parfaitement ordinaire.

Autres conseils

Plus-que fonctionne la comparaison parce que, par défaut, il fonctionne pour tous les objets.

>>> 'abc' > 123
True

Decimal est juste simplement parce qu'il suit correctement la spécification. Que la spécification était la bonne approche est une question distincte. :)

Seules les mises en garde normales lorsqu'ils traitent avec les flotteurs, qui a brièvement résumés sont les suivants: méfiez-vous des cas de pointe comme zéro négatif, +/- l'infini et NaN, ne testent pas pour l'égalité (lié au point suivant), et le nombre sur les mathématiques étant légèrement inexact.

>>> print (1.1 + 2.2 == 3.3)
False

Si elle est « droit » est une question d'opinion, mais la raison d'être des raisons pour lesquelles il n'y a pas de conversion automatique existe dans le PEP, et qui a été la décision prise. La mise en garde est fondamentalement que vous ne pouvez pas toujours exactement convertir entre flotteur et décimal. Par conséquent, la conversion ne doit pas être implicite. Si vous dans votre application sachez que vous n'avez jamais assez grand nombre pour que cela vous affecte, faire des classes qui permettent ce comportement implicite ne devrait pas être un problème.

En outre, un argument principal est que dans le monde réel des cas d'utilisation n'existe pas. Il est susceptible d'être plus simple si vous utilisez seulement décimal partout.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top