Je reçois une erreur de débordement (OverflowError: (34, 'Résultat trop important')
Je veux calculer pi à 100 décimales, voici mon code:
def pi():
pi = 0
for k in range(350):
pi += (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k
return pi
print(pi())
Les flotteurs Python ne sont ni une précision arbitraire ni une taille illimitée. Lorsque k = 349, 16.**k
est beaucoup trop grand - c'est presque 2 ^ 1400. Heureusement, la bibliothèque decimal
permet une précision arbitraire et peut gérer la taille:
import decimal
decimal.getcontext().prec = 100
def pi():
pi = decimal.Decimal(0)
for k in range(350):
pi += (decimal.Decimal(4)/(decimal.Decimal(8)*decimal.Decimal(k+1))...)
Vous avez atteint les limites du support float
de votre plate-forme, probablement après le k = 256
:
>>> k = 256
>>> (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: (34, 'Result too large')
>>> k = 255
>>> (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k
3.19870064997e-313
Voir sys.float_info
pour les limitations exactes, mais il est peu probable que vous rencontriez une combinaison actuelle de processeur et de système d'exploitation qui vous donnera 100 chiffres significatifs dans tous les cas. Mon MacBook Pro avec OS X 64 bits ne prend en charge que 15 ordinateurs.
Utilisez le module decimal
pour dépasser les limitations de votre matériel.
from decimal import Decimal, localcontext
def pi():
with localcontext() as ctx:
ctx.prec = 100 # 100 digits precision
pi = Decimal(0)
for k in range(350):
pi += (Decimal(4)/(Decimal(8)*k+1) - Decimal(2)/(Decimal(8)*k+4) - Decimal(1)/(Decimal(8)*k+5) - Decimal(1)/(Decimal(8)*k+6)) / Decimal(16)**k
return pi
J'utilise python3.6 AMD64, je rencontre également ce problème, car python float
est une variable double précision, elle est à 64 bits, dans la plupart des tâches de programmation, 64 bits suffisent, assez (comme l'informatique scientifique, l'informatique big data)
16. ** 256 est trop grand pour être stocké dans un float à double précision. Je suggère que vous exécutiez votre cycle moins cher, comme dans l'intervalle (250), car des valeurs k plus grandes ne contribueront de toute façon pas aux cent premiers chiffres.
Une autre chose que vous pourriez essayer est de multiplier par 16. * (-k) au lieu de diviser par 16. * k. Ce nombre sera arrondi à zéro pour le grand k, donc ne vous donnera pas d'erreur d'exécution.
Je suggère que vous utilisiez numpy.power au lieu de **, il gère mieux les débordements. Par exemple, dans votre code numpy.power (16., 256) serait évalué à inf, et diviser un nombre fini par inf donne zéro, ce qui évite les erreurs d'exécution tout comme le fait la méthode proposée dans le paragraphe précédent.