En gros, je convertis un float en int, mais je n’ai pas toujours la valeur attendue.
Voici le code que j'exécute:
x = 2,51
print("--------- 251.0")
y = 251.0
print(y)
print(int(y))
print("--------- 2.51 * 100")
y = x * 100
print(y)
print(int(y))
print("--------- 2.51 * 1000 / 10")
y = x * 1000 / 10
print(y)
print(int(y))
print("--------- 2.51 * 100 * 10 / 10")
y = x * 100 * 10 / 10
print(y)
print(int(y))
x = 4.02
print("--------- 402.0")
y = 402.0
print(y)
print(int(y))
print("--------- 4.02 * 100")
y = x * 100
print(y)
print(int(y))
print("--------- 4.02 * 1000 / 10")
y = x * 1000 / 10
print(y)
print(int(y))
print("--------- 4.02 * 100 * 10 / 10")
y = x * 100 * 10 / 10
print(y)
print(int(y))
Et voici le résultat (la première valeur est le résultat de l'opération, la deuxième valeur est int () de la même opération):
--------- 251.0
251.0
251
--------- 2.51 * 100
251.0
250
--------- 2.51 * 1000 / 10
251.0
251
--------- 2.51 * 100 * 10 / 10
251.0
250
--------- 402.0
402.0
402
--------- 4.02 * 100
402.0
401
--------- 4.02 * 1000 / 10
402.0
401
--------- 4.02 * 100 * 10 / 10
402.0
401
2.51 et 4.02 sont les seules valeurs qui conduisent à ce comportement étrange sur la plage 2.50 -> 5.00. Une valeur sur deux chiffres dans cette plage est convertie en int sans aucun problème lorsque les mêmes opérations sont effectuées.
Alors, qu'est-ce qui me manque pour arriver à ces résultats? J'utilise Python 2.7.2 en passant.
2.51 * 100 = 250.999999999997
La fonction int()
tronque simplement le nombre à la virgule décimale pour donner 250. Utilisez
int(round(2.51*100))
pour obtenir 251 comme un entier. En général, les nombres en virgule flottante ne peuvent pas être représentés exactement. Il faut donc faire attention aux erreurs d'arrondis. Comme mentionné, ce n'est pas un problème spécifique à Python. C'est un problème récurrent dans tous les langages informatiques.
Ce que tous les informaticiens devraient savoir sur l’arithmétique en virgule flottante
Les nombres en virgule flottante ne peuvent pas représenter tous les nombres. En particulier, 2.51 ne peut pas être représenté par un nombre à virgule flottante, mais par un nombre très proche de celui-ci:
>>> print "%.16f" % 2.51
2.5099999999999998
>>> 2.51*100
250.99999999999997
>>> 4.02*100
401.99999999999994
Si vous utilisez int, qui tronque les nombres, vous obtenez:
250
401
Regardez le type Décimal .
Les langages qui utilisent des représentations à virgule flottante binaire (Python en est un) ne peuvent pas représenter toutes les valeurs fractionnaires de manière exacte. Si le résultat de votre calcul est 250,99999999999 (et il se peut qu'il le soit), le fait de prendre la partie entière correspondra à 250.
Un article canonique sur ce sujet est Ce que tout informaticien devrait savoir sur l'arithmétique en virgule flottante .
>>> x = 2.51
>>> x*100
250.99999999999997
les nombres en virgule flottante sont inexacts. dans ce cas, il s'agit de 250.99999999999999, ce qui est vraiment proche de 251, mais int () tronque la partie décimale, dans ce cas 250.
vous devriez jeter un oeil au module Decimal ou peut-être si vous devez faire beaucoup de calculs à la bibliothèque mpmath http://code.google.com/p/mpmath/ :),
int
convertit par troncature, comme cela a été mentionné par d'autres. Cela peut entraîner une réponse différente de celle attendue. Une solution consiste à vérifier si le résultat est "assez proche" d'un entier et à ajuster en conséquence, sinon la conversion habituelle. En supposant que vous n'obtenez pas trop d'arrondis et d'erreur de calcul, ce qui est un problème distinct. Par exemple:
def toint(f):
trunc = int(f)
diff = f - trunc
# trunc is one too low
if abs(f - trunc - 1) < 0.00001:
return trunc + 1
# trunc is one too high
if abs(f - trunc + 1) < 0.00001:
return trunc - 1
# trunc is the right value
return trunc
Cette fonction s'ajustera pour les erreurs off-by-one des quasi-entiers. La bibliothèque mpmath
fait quelque chose de similaire pour les nombres à virgule flottante proches des nombres entiers.