web-dev-qa-db-fra.com

Le moyen le plus sûr de convertir float en entier en python?

Le module mathématique de Python contient des fonctions pratiques telles que floor & ceil. Ces fonctions prennent un nombre à virgule flottante et renvoient l'entier le plus proche en dessous ou au dessus. Cependant, ces fonctions renvoient la réponse sous forme de nombre à virgule flottante. Par exemple:

import math
f=math.floor(2.3)

Maintenant f retourne:

2.0

Quel est le moyen le plus sûr d’obtenir un entier de ce nombre, sans risquer d’arrondir (par exemple, si le nombre est équivalent à 1,99999) ou d’utiliser une autre fonction?

172
Boaz

Tous les entiers pouvant être représentés par des nombres à virgule flottante ont une représentation exacte. Vous pouvez donc utiliser int en toute sécurité. Les représentations inexactes ne se produisent que si vous essayez de représenter un nombre rationnel avec un dénominateur qui n'est pas une puissance de deux.

Que cela fonctionne n'est pas trivial du tout! C'est une propriété de la représentation à virgule flottante IEEE qui int∘floor = ⌊⋅⌋ si la magnitude des nombres en question est suffisamment petite, mais différentes représentations sont possibles où int (floor (2.3)) pourrait être 1.

Pour citer de Wikipedia ,

Tout nombre entier avec une valeur absolue inférieure ou égale à 224 peut être exactement représenté dans le format simple précision, et tout nombre entier avec une valeur absolue inférieure ou égale à 253 peut être exactement représenté dans le format double précision.

150
Philipp

Utilisez int(your non integer number) va le clouer.

print int(2.3) # "2"
print int(math.sqrt(5)) # "2"
91
srodriguex

Vous pouvez utiliser la fonction round. Si vous n'utilisez pas de second paramètre (nombre de chiffres significatifs), je pense que vous obtiendrez le comportement souhaité.

Sortie IDLE.

>>> round(2.99999999999)
3
>>> round(2.6)
3
>>> round(2.5)
3
>>> round(2.4)
2
43
Wade73

En combinant deux des résultats précédents, nous avons:

int(round(some_float))

Cela convertit un float en entier de manière assez fiable.

38
user3763109

Que cela fonctionne n'est pas trivial du tout! C'est une propriété de la représentation à virgule flottante IEEE qu'int∘floor = ⌊⋅⌋ si la magnitude des nombres en question est suffisamment petite, mais que des représentations différentes sont possibles, où int (floor (2.3)) pourrait être 1.

Cet article explique pourquoi cela fonctionne dans cette plage .

Dans un double, vous pouvez représenter des entiers 32 bits sans aucun problème. Il ne peut pas avoir de problème d'arrondi. Plus précisément, les doubles peuvent représenter tout entiers compris entre et compris 253 et - 253.

Explication courte: Un double peut stocker jusqu'à 53 chiffres binaires. Lorsque vous avez besoin de plus, le nombre est complété par des zéros à droite.

Il en résulte que 53 unités est le plus grand nombre pouvant être stocké sans remplissage. Naturellement, tous les nombres (entiers) nécessitant moins de chiffres peuvent être stockés avec précision.

Ajouter un à 111 (omis) 111 (53 unités) donne 100 ... 000, (53 zéros). Comme nous le savons, nous pouvons stocker 53 chiffres, ce qui constitue le remplissage zéro le plus à droite.

C'est là 253 vient de.


Plus de détail: Nous devons examiner le fonctionnement de la virgule flottante IEEE-754.

  1 bit    11 / 8     52 / 23      # bits double/single precision
[ sign |  exponent | mantissa ]

Le nombre est ensuite calculé comme suit (à l'exception des cas spéciaux sans importance ici):

- 1signe × 1.mantissa × 2exposant - biais

biais = 2exposant - 1 - 1 , c’est-à-dire 1023 et 127 pour une précision double/simple, respectivement.

Sachant que multiplier par 2X décale simplement tous les bits X à gauche, il est facile de voir que tout entier doit avoir tous les bits dans la mantisse qui finissent à droite du point décimal.

Tout nombre entier sauf zéro a la forme suivante en binaire:

1x ... x où les x - es représentent les bits à la droite du bit de poids fort (bit le plus significatif).

Comme nous avons exclu zéro, il y aura toujours un MSB identique, raison pour laquelle il n'est pas stocké. Pour stocker le nombre entier, nous devons le mettre sous la forme susmentionnée: - 1signe × 1.mantissa × 2exposant - biais.

Cela signifie la même chose que de déplacer les bits sur le point décimal jusqu'à ce qu'il n'y ait plus que le MSB vers la gauche du MSB. Tous les bits à droite du point décimal sont ensuite stockés dans la mantisse.

De là, nous pouvons voir que nous pouvons stocker au plus 52 chiffres binaires en dehors du MSB.

Il en résulte que le nombre le plus élevé où tous les bits sont explicitement stockés est

111(omitted)111.   that's 53 ones (52 + implicit 1) in the case of doubles.

Pour cela, nous devons définir l’exposant, de sorte que le point décimal soit décalé de 52 places. Si nous devions augmenter l'exposant de un, nous ne pourrions pas connaître le chiffre situé à droite après le point décimal.

111(omitted)111x.

Par convention, il est égal à 0. En mettant la mantisse entière à zéro, nous recevons le nombre suivant:

100(omitted)00x. = 100(omitted)000.

C'est un 1 suivi de 53 zéros, 52 stockés et 1 ajouté en raison de l'exposant.

Cela représente 253, qui marque la limite (à la fois négative et positive) entre laquelle nous pouvons représenter avec précision tous les entiers. Si nous voulions en ajouter un à 253, il faudrait mettre le zéro implicite (désigné par le x) à un, mais c'est impossible.

18
phant0m

math.floor renverra toujours un nombre entier et donc int(math.floor(some_float)) ne provoquera jamais d'erreurs d'arrondi.

L’erreur d’arrondi est peut-être déjà introduite dans math.floor(some_large_float), cependant, ou même lors du stockage d’un nombre élevé dans un float. (Un grand nombre peut perdre en précision lorsqu'il est stocké dans des flotteurs.)

5
user3850

Si vous avez besoin de convertir une chaîne float en int, vous pouvez utiliser cette méthode.

Exemple: '38.0' à 38

Afin de convertir ceci en int, vous pouvez le lancer comme un float puis un int. Cela fonctionnera également pour les chaînes flottantes ou les chaînes entières.

>>> int(float('38.0'))
38
>>> int(float('38'))
38

Note : Ceci effacera tous les nombres après la virgule.

>>> int(float('38.2'))
38
4
brandonbanks

Un autre exemple de code permettant de convertir un nombre réel/flottant en un entier à l'aide de variables . "Vel" correspond à un nombre réel/flottant converti au prochain nombre entier INTEGER, "newvel".

import arcpy.math, os, sys, arcpy.da
.
.
with arcpy.da.SearchCursor(densifybkp,[floseg,vel,Length]) as cursor:
 for row in cursor:
    curvel = float(row[1])
    newvel = int(math.ceil(curvel))
1
mrichey56

Puisque vous demandez le moyen le plus sûr, je vais vous donner une autre réponse que la réponse principale.

Un moyen simple de vous assurer de ne perdre aucune précision est de vérifier si les valeurs sont égales après les avoir converties. 

if int(some_value) == some_value:
     some_value = int(some_value)

Si le flottant est 1.0 par exemple, 1.0 est égal à 1. La conversion en int s'exécutera donc. Et si le float est 1.1, int (1.1) équivaut à 1 et 1.1! = 1. La valeur restera donc un float et vous ne perdrez aucune précision.

0
Troy H