2017-07-24 2 views
1

Dans mon programme, j'utilise numpy pour obtenir les exposants du nombre, puis j'utilise la fonction sum pour les résumer. J'ai remarqué que résumer ces grands nombres, avec ou sans numpy, donne le plus grand paramètre retourné, inchangé.La sommation de grands nombres en python donne le paramètre maximal

exp_joint_probabilities=[ 1.57171938e+81, 1.60451506e+56, 1.00000000e+00] 
exp_joint_probabilities.sum() 
=> 1.571719381352921e+81 

La même chose avec python juste:

(1.57171938e+81+1.60451506e+56+1.00000000e+00)==1.57171938e+81 
=>True 

Est-ce un problème avec une approximation? Dois-je utiliser un type de données plus grand pour représenter les nombres? Comment puis-je obtenir un résultat plus précis pour ce genre de calculs?

Répondre

1

1.57171938e+81 est un nombre à 81 chiffres, dont vous ne entrez le premier 9. 1.60451506e+56 est un nombre beaucoup beaucoup plus petit, avec seulement 56 chiffres.

Quel genre de réponse attendez-vous? Le premier éclipse complètement le second. Si vous voulez quelque chose d'une précision similaire à vos chiffres d'origine (et c'est ce que vous obtenez en utilisant des flottants), alors la réponse est tout simplement correcte.

Vous pouvez utiliser ints:

>>> a = int(1.57171938e+81) 
>>> b = int(1.60451506e+56) 
>>> a 
571719379999999945626903548020224083024251666384876684446269499489505292916359168L 
>>> b 
160451506000000001855754747064077065047170486040598151168L 
>>> a+b 
1571719379999999945626903708471730083024253522139623748523334546659991333514510336L 

Mais comment utile qui est est à vous.

0

Il ne semble pas être un problème avec approximation:

>>> 1.57171938e+81 + 1.60451506e+65 > 1.57171938e+81 
<<< True 

>>> 1.57171938e+81 + 1.60451506e+64 > 1.57171938e+81 
<<< False 

Vous pouvez obtenir arount ce par à int:

>>> int(1.57171938e+81) + int(1.60451506e+64) > int(1.57171938e+81) 
<<< True 
+0

Le casting 'de long' ne fonctionne pas en Python 3.x. Casting à 'int' fonctionne là et je crois que cela fonctionne aussi dans Python 2.x. –

+0

'int' confirmé pour travailler à cet effet dans Python 2.7 – Marein

+0

Oh, je ne savais pas que' int' travaillé dans ce cas, je vais modifier ma réponse, merci. – iCart

2

Vous pouvez utiliser the decimal standard library:

from decimal import Decimal 

a = Decimal(1.57171938e+81) 
b = Decimal(1.60451506e+56) 
d = a + b 
print(d) 
print(d > a and d > b) 

Sortie:

1.571719379999999945626903708E+81 
True 

Vous pouvez reconvertir en un flotteur après, mais cela entraînera le même problème qu'auparavant.

f = float(d) 
print(f) 
print(f > a and f > b) 

Sortie:

1.57171938e+81 
False 

Notez que si vous stockez Decimal s dans vos numpy tableaux, vous perdrez des opérations vectorisés rapide, comme numpy does not recognize Decimal objects. Bien qu'il fonctionne:

import numpy as np 

a = np.array([1.57171938e+81, 1.60451506e+56, 1.00000000e+00]) 
d = np.vectorize(Decimal)(a) # convert values to Decimal 
print(d.sum()) 
print(d.sum() > d[0] 

Sortie:

1.571719379999999945626903708E+81 
True 
+1

Vous commencez toujours par convertir les nombres en approximations flottantes 64 bits, puis en approximant les valeurs décimales. Pour convertir directement l'entrée en Decimal, donnez-les comme des chaînes, 'a = Decimal (" 1.57171938e + 81 ")' et 'b = Decimal (" 1.60451506e + 56 ")' alors 'a + b' donne le résultat le plus correct 'Decimal ('1.571719380000000000000000160E + 81 ') ' – LutzL