web-dev-qa-db-fra.com

Python conversion de float en int

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.

62
B. Richard
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.

79
Pascal Bugnion

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 .

32
Jacob

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 .

10
Greg Hewgill
>>> 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/ :),

7
Ant

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.

1
HackerBoss