2015-12-17 1 views
1

Je stocke un tas de données au format entier dans une table pytables. Les données sont factorisées sur les chaînes stockées flottantes, pour éviter toute perte de précision. À titre d'exemple:Arrondir les champs PyTables avec round()

>>> src.root.Timeseries.M1[0][5] 
668000 

Si i facteur sur le nombre brut, j'obtenir le bon résultat:

>>> round(668000/100000.0, 2) 
6.68 

Mais si je facteur sur la valeur int du champ PyTables, round() doesn « t travail du tout:

>>> round(src.root.Timeseries.M1[0][5]/100000.0, 2) 
6.6799999999999997 

le champ PyTables est définie par le type de données Int64Col().

Des idées sur ce qui se passe?

Répondre

1

Votre problème n'a rien à voir avec PyTables. PyTables vous donne un tableau NumPy.

Par exemple, nous allons utiliser un tableau très simple:

>>> import numpy as np 
>>> a = np.array([668000 ]) 
>>> a[0] 
668000 

Lorsque vous autour de ce numéro que vous obtenez

>>>round(a[0]/100000.0, 2) 
6.6799999999999997 

Ceci est parce qu'il a le type numpy.float64:

>>>type(round(a[0]/100000.0, 2)) 
numpy.float64 

La conversion en Python float indique le résultat le plus court:

>>> float(round(a[0]/100000.0, 2)) 
6.68 

Vous devriez obtenir quelque chose comme ceci:

>>> float(round(src.root.Timeseries.M1[0][5]/100000.0, 2)) 
6.68 

Les valeurs numériques n'a pas changé. Tout est juste une question comment le nombre est représenté. Le standard Python float est représenté un peu mieux la version NumPy. Floating point numbers sont un sujet compliqué après tout.

La façon dont un objet est représenté en Python est déterminé par la méthode spéciale __repr__():

>>> round(a[0]/100000.0, 2).__repr__() 
'6.6799999999999997' 

Ce qui est utilisé ici:

>>> round(a[0]/100000.0, 2) 
6.6799999999999997 

Il existe une autre méthode spéciale __str()__:

>>> round(a[0]/100000.0, 2).__str__() 
'6.68' 

Il est implicitement utilisé lorsque vous imprimez un ob Ject:

>>> print(round(a[0]/100000.0, 2)) 
6.68 

+0

Intéressant. Surtout que j'avais l'espoir que round() retournerait un nouveau nombre avec beaucoup moins de décimales. En fait seulement 2 comme utilisé dans le deuxième paramètre. Est-ce que je tire la bonne conclusion quand je suppose que round() ne fonctionne pas sur dtypes numpy? Comment "Ce n'est qu'une question de savoir comment le nombre est représenté" n'est pas tout à fait clair pour moi.La raison de la confusion, c'est que lancer à float(), par expérience, en soi ne sera pas toujours un nombre exact. Donc, je pense actuellement que je ne suis pas plus proche de l'objectif initial de la représentation exacte. –

+0

C'est le même numéro. Seule la façon dont il vous est montré est différente. Voir ma réponse mise à jour. –

+0

Merci pour votre clarification. Apprendre cela, je recon en utilisant Decimal sera le moyen de maintenir la précision. La pénalité d'utiliser cDecimal est d'environ 119% de temps de calcul supplémentaire, mais je ne peux pas vivre avec l'alternative. –