web-dev-qa-db-fra.com

Comment obtenir la plus grande précision possible? (Python - Décimal)

J'utilise la classe Decimal pour les opérations nécessitant une précision.

Je voudrais utiliser la plus grande précision possible. Par cela, je veux dire aussi précis que le système sur lequel le programme s'exécute peut gérer.

Pour définir une certaine précision, c'est simple:

import decimal
decimal.getcontext().prec = 123 #123 decimal precision

J'ai essayé de comprendre la précision maximale que la classe 'Decimal' peut calculer:

print(decimal.MAX_PREC)
>> 999999999999999999

J'ai donc essayé de régler la précision au maximum (sachant que cela ne fonctionnerait probablement pas ..):

decimal.getcontext().prec = decimal.MAX_PREC

Mais, bien sûr, cela jette un Memory Error (sur division)

Ma question est donc la suivante: comment déterminer la précision maximale que le système actuel peut gérer?

Informaitons supplémentaires:

import sys
print(sys.maxsize)
>> 9223372036854775807
10
Eli

Essayer de faire cela est une erreur. Donner plus de précision à un problème est un piège tentant pour les nouveaux venus en virgule flottante, mais ce n’est pas très utile, surtout à ce point extrême.

Vos opérations ne nécessiteraient pas réellement la précision "la plus grande possible", même s’il s’agissait d’une notion bien définie. Soit ils nécessitent l'arithmétique exact, auquel cas decimal.Decimal est un outil totalement incorrect et vous devriez vous pencher sur quelque chose comme fractions.Fraction ou le calcul symbolique, ou bien ils n'exigent pas autant de précision et vous devez déterminer leur précision a réellement besoin de et utilise ça.

Si vous voulez toujours apporter toute la précision que vous pouvez sur votre problème, sa précision dépendra du type de calcul que vous faites et du nombre absurdement précis que vous essayez de stocker en mémoire en une fois. . Cela peut être déterminé en analysant votre programme et les besoins en mémoire des objets Decimal. Vous pouvez également utiliser la précision en tant que paramètre et recherche binaire de la précision la plus grande ne provoquant pas de panne.

9
user2357112

J'aimerais suggérer une fonction qui vous permet d'estimer votre précision maximale pour une opération donnée de manière brutale:

def find_optimum(a,b, max_iter):
    for i in range(max_iter):
        print(i)
        c = int((a+b)/2)
        decimal.getcontext().prec = c
        try:
            dummy = decimal.Decimal(1)/decimal.Decimal(7) #your operation
            a = c
            print("no fail")
        except MemoryError:
            print("fail")
            dummy = 1
            b = c
        print(c)
        del dummy

Il ne s'agit que de diviser par deux les intervalles, un pas à la fois, et de rechercher une erreur éventuelle. Appeler avec max_iter=10 et a=int(1e9), b=int(1e11) donne:

>>> find_optimum(int(1e9), int(1e11), 10)
0
fail
50500000000
1
no fail
25750000000
2
no fail
38125000000
3
no fail
44312500000
4
fail
47406250000
5
fail
45859375000
6
no fail
45085937500
7
no fail
45472656250
8
no fail
45666015625
9
no fail
45762695312

Cela peut donner une idée approximative de ce à quoi vous avez affaire. Cela a pris environ une demi-heure sous i5-3470 et 16 Go RAM, vous ne l'utiliseriez donc qu'à des fins de test. 

Je ne pense pas qu’il existe un moyen exact d’obtenir la précision maximale pour votre opération, car vous auriez besoin de connaître exactement la dépendance de votre utilisation de la mémoire à la consommation de mémoire. J'espère que cela vous aide au moins un peu et j'aimerais vraiment savoir pourquoi vous avez besoin de ce genre de précision.

EDITJe pense que cela doit vraiment être ajouté, car j'ai lu vos commentaires sous l'article le mieux noté ici. En utilisant une précision arbitrairement élevée de cette manière, les gens ne calculent pas les constantes. Vous programmez quelque chose qui utilise intelligemment l’espace disque (par exemple, en calculant un tas de chiffres dans RAM et en écrivant ce tas dans un fichier texte), sans jamais utiliser uniquement la mémoire vive/permutation, car limiter vos résultats. Avec les algorithmes modernes pour calculer les pi, vous n’avez pas besoin d’une RAM infinie, vous devez simplement insérer un autre disque dur de 4 To dans la machine et le laisser écrire les prochains chiffres. Jusqu'ici pour les constantes mathématiques.

Passons maintenant aux constantes physiques: elles ne sont pas précises. Ils comptent sur la mesure. Je ne suis pas sûr que atm (éditera) mais je pense que la constante physique la plus exacte a une erreur de 10 ** (- 8). Jeter plus de précision dessus, ne le rend pas plus exact, vous calculez simplement plus de faux nombres.

En guise d’expérience, c’était une idée amusante, c’est pourquoi j’ai même posté la réponse.

4
user8408080

La précision maximale de la classe Decimal est fonction de la mémoire de l'appareil. Il n'y a donc aucun moyen de la définir dans le cas général. Fondamentalement, vous allouez toute la mémoire de la machine à une variable pour obtenir une précision maximale.

Si l'opération mathématique le supporte, les entiers longs vous donneront une précision illimitée. Cependant, vous êtes limité à des nombres entiers.

L'addition, la soustraction, la multiplication et les exposants simples peuvent être effectués exactement avec des entiers longs.

Avant Python 3, le type de données intégré long effectuait des calculs de précision arbitraires . https://docs.python.org/2/library/functions.html#long

Dans Python> = 3, le type de données int représente désormais des entiers longs . https://docs.python.org/3/library/functions.html#int

Un exemple de calcul de nombre entier sur 64 bits est l'implémentation de bitcoind, où les calculs de transaction nécessitent des valeurs exactes. Cependant, la précision des transactions Bitcoin est limitée à 1 "Satoshi"; chaque Bitcoin est défini comme étant 10 ^ 8 (entier) Satoshi.

La classe Decimal fonctionne de manière similaire sous le capot. Une précision décimale de 10 ^ -8 est similaire au paradigme Bitcoin-Satoshi.

2
Chris Hubley

De votre réponse ci-dessus:

Et si je voulais juste trouver plus de chiffres en pi que ceux déjà trouvés? Et si je voulais tester l'irrationalité de la constante de e ou mill.

J'ai compris. Je fais vraiment. Ma one SO question , vieille de plusieurs années, concerne les bibliothèques à virgule flottante de précision arbitraire pour Python. Si ce sont les types de représentations numériques que vous voulez générer, soyez prêt pour la plongée profonde. L'arithmétique décimale/PF est notoirement difficile en informatique. 

Certains programmeurs, confrontés à un problème, se disent: «Je sais, je vais utiliser l’arithmétique en virgule flottante». Ils ont maintenant des problèmes 1.999999999997. - @tomscott

Je pense que lorsque d’autres ont dit que c’était une "erreur" ou "cela dépend" de se demander quelle est la précision maximale pour un type Python Decimal sur une plate-forme donnée, ils prennent votre question plus au sens littéral que je ne le pensais. Vous avez posé une question sur le type décimal Python, mais si vous êtes intéressé par l'arithmétique de FP à des fins pédagogiques - "pour trouver plus de chiffres en pi" - vous aurez besoin d'outils plus puissants et plus flexibles que Décimal ou float . Ces types Python intégrés ne viennent même pas close. Celles-ci sont assez bonnes pour la NASA peut-être, mais elles ont des limites… en fait, les limites mêmes que vous demandez.

C’est ce que les bibliothèques à virgule flottante à précision multiple (ou arbitraire-precision ) désignent pour: des représentations à la précision arbitraire. Vous voulez calculer pi pour les 20 prochaines années? Le type décimal de Python ne vous permettra même pas de traverser le jour.

Le fait est que l'arithmétique binaire multi-précision FP est encore un peu une science marginale. Pour Python, vous devez installer la bibliothèque GNU MPFR sur votre machine Linux. Vous pouvez ensuite utiliser la bibliothèque Python gmpy2 pour plonger aussi profondément que vous le souhaitez. 

Ensuite, la question n'est pas "Quelle est la précision maximale que mon programme peut utiliser?"

C'est: "Comment puis-je écrire mon programme pour qu'il continue jusqu'à ce que l'électricité soit coupée?"

Et c'est un tout autre problème, mais au moins il est limité par votre algorithme, pas par le matériel sur lequel il tourne.

0
Joseph8th