Des précisions sur le type Décimal en Python
Tout le monde sait, ou au moins, tous les programmeurs doivent savoir, que l'utilisation de la float
type pourrait conduire à des erreurs de précision. Toutefois, dans certains cas, une solution exacte serait bien et il ya des cas où la comparaison à l'aide d'une valeur epsilon n'est pas assez. De toute façon, ce n'est pas vraiment le point.
Je savais à propos de la Decimal
type en Python, mais je n'ai jamais essayé de l'utiliser. Il affirme que "Décimal les nombres peuvent être représentés exactement" et j'ai pensé qu'il s'agissait d'une habile mise en œuvre qui permet de représenter n'importe quel nombre réel. Mon premier essai était:
>>> from decimal import Decimal
>>> d = Decimal(1) / Decimal(3)
>>> d3 = d * Decimal(3)
>>> d3 < Decimal(1)
True
Assez déçu, je suis rentré à la documentation et à gardé lecture:
Le contexte de l'arithmétique est un environnement de spécification de précision [...]
Ok, donc il y a effectivement une précision. Et les questions classiques qui peuvent être reproduites:
>>> dd = d * 10**20
>>> dd
Decimal('33333333333333333333.33333333')
>>> for i in range(10000):
... dd += 1 / Decimal(10**10)
>>> dd
Decimal('33333333333333333333.33333333')
Donc, ma question est: est-il un moyen d'avoir un type Décimal avec une précision infinie? Si non, quel est le moyen plus élégant de la comparaison de 2 nombres décimaux (p. ex. d3 < 1 doit retourner False si le delta est inférieur à la précision).
Actuellement, quand je ne fais que des divisions et des multiplications, j'utilise le Fraction
type:
>>> from fractions import Fraction
>>> f = Fraction(1) / Fraction(3)
>>> f
Fraction(1, 3)
>>> f * 3 < 1
False
>>> f * 3 == 1
True
Est-il la meilleure approche? Quelles pourraient être les autres options?
- comment voulez-vous vous représenter
Pi
avec votre hypothétique de type Décimal? - connexes: Comment est-il dangereux pour comparer les valeurs à virgule flottante?
- Je ne serais pas surpris si possible. C'est pourquoi je pose la question "quel est le moyen plus élégant de la comparaison de 2 nombres décimaux".
- Je pense aussi à un type qui me permettent de nombreuses manipulations (opérations de base, des fonctions communes, etc), mais de garder une représentation exacte. Par exemple, la Fraction type semble gérer parfaitement de nombreux cas. En fait, toute fois, le résultat n'est pas un nombre irrationnel. Mais peut-être qu'on pourrait faire mieux avec une autre représentation qui permettrait d'inclure un plus grand sous-ensemble. Quelque chose de dynamique, de précision, comme un gamin le ferait à l'école par exemple. Bien sûr, je ne pouvais pas représenter
Pi
, mais assez souvent,Pi
est juste une constante du problème. - Avant de réinventer la roue avec votre représentation exacte, jetez un oeil à la Sauge ou sympy
- J'ai été la lecture de la documentation de SymPy, mais je ne peux pas trouver un type (qui pourrait remplacer directement en Décimal). Mais en effet, SymPy, qui n'calcul symbolique, pourrait sans doute faire l'affaire.
Vous devez vous connecter pour publier un commentaire.
Le séparateur Décimal est la classe la mieux financière de type addition, de la soustraction la multiplication, la division type de problèmes:
La Fraction module fonctionne bien avec le nombre rationnel du domaine du problème que vous décrivez:
Pour multi précision à virgule flottante pour le travail scientifique, envisager mpmath.
Si votre problème ne peut être tenu pour le domaine symbolique, envisager sympy. Voici comment vous pourriez gérer le 1/3 question:
Sympy utilise mpmath pour arbitraire de précision à virgule flottante, comprend la capacité de manipuler des nombres rationnels et des nombres irrationnels symboliquement.
Envisager la pure représentation à virgule flottante de l'irrationnel, de la valeur de √2:
Comparer à sympy:
Vous pouvez également réduire les valeurs:
Cependant, vous pouvez voir les problèmes avec Sympy semblable à droite à virgule flottante si vous ne faites pas attention:
Il vaut mieux le faire avec Décimale:
Ou à l'aide de Fractions ou Sympy et en gardant des valeurs telles que la
1.1
comme des ratios:Ou de l'utilisation Rationnelle dans sympy:
Vous pouvez jouer avec sympy vivre.
Pas, depuis le stockage d'un nombre irrationnel aurait besoin infini de la mémoire.
Où
Decimal
est utile est le fait de représenter des choses comme des montants monétaires, où les valeurs doivent être exactes et la précision est connue a priori.De la question, il n'est pas tout à fait clair que
Decimal
est le plus approprié pour votre cas d'utilisation defloat
.Fraction
précisément) et ces résultats ont réellement besoin infini de la mémoire (et/ou un temps infini), par exemple,sqrt(2)
,Pi
.storing an irrational number would require infinite memory
Ils n'ont besoin infini de la mémoire si elle est représentée comme nombres à virgule flottante. Vous pouvez représenter les nombres irrationnels comme un objet symbolique, bien sûr. Wolfram alpha. en mathématiques, et sympy ce faire.Pas; pour tout non-vide de l'intervalle sur la ligne réelle, vous ne peut pas représenter tous les nombres de l'ensemble avec une infinie précision à l'aide d'un nombre fini de bits. C'est pourquoi
Fraction
est utile, car il stocke le numérateur et le dénominateur par des entiers, qui peut être représenté précisément:Fraction('1.25')
est plus sûr, que de fournir un flotteur littéral peut présenter le même problème que vous essayez d'éviter (à savoir,Fraction
ne reçoit pas la valeur exacte destiné à fournir).π
et√2
symboliquement et effectuer exacte des calculs avec eux (par exemple,√2√3 = √6
,cos(π)=-1
). Cela peut être fait dans les limites de la mémoire disponible comme pour les grands entiers. Je pense que ce que tu veux dire, c'est: pour tout intervalle non vide sur la ligne réelle, vous ne pouvez pas représenter tous nombres de l'ensemble avec une infinie précision à l'aide d'un nombre fini de bits.Si vous êtes nouveau à la Virgule, ce post est pertinent: Python à virgule flottante en précision arbitraire disponible?
L'idée essentielle de l'réponses et commentaires, c'est que pour le calcul des problèmes difficiles où la précision est nécessaire, vous devez utiliser le
mpmath
module https://code.google.com/p/mpmath/. Une observation importante est que,