texto - ¿La forma más segura de convertir float a entero en python?
pasar de float a int python (8)
¡Que esto funcione no es trivial en absoluto! Es una propiedad de la representación de punto flotante IEEE que int∘floor = ⌊⋅⌋ si la magnitud de los números en cuestión es lo suficientemente pequeña, pero son posibles diferentes representaciones donde int (piso (2.3)) podría ser 1.
Esta publicación explica por qué funciona en ese rango .
En un doble, puede representar enteros de 32 bits sin ningún problema. No puede haber problemas de redondeo. Más precisamente, los dobles pueden representar todos los enteros entre e incluyendo 2 53 y -2 53 .
Breve explicación : un doble puede almacenar hasta 53 dígitos binarios. Cuando necesita más, el número se rellena con ceros a la derecha.
Se deduce que 53 uno es el número más grande que se puede almacenar sin relleno. Naturalmente, todos los números (enteros) que requieren menos dígitos se pueden almacenar con precisión.
Sumando uno a 111 (omitido) 111 (53 unos) rinde 100 ... 000, (53 ceros). Como sabemos, podemos almacenar 53 dígitos, lo que hace que el relleno en el extremo derecho sea cero.
De aquí viene el 2 53 .
Más detalles: tenemos que considerar cómo funciona el punto flotante IEEE-754.
1 bit 11 / 8 52 / 23 # bits double/single precision
[ sign | exponent | mantissa ]
El número se calcula de la siguiente manera (excluyendo casos especiales que son irrelevantes aquí):
-1 signo × 1.mantissa × 2 exponente - parcialidad
donde bias = 2 exponente - 1 - 1 , es decir, 1023 y 127 para precisión doble / simple respectivamente.
Sabiendo que la multiplicación por 2 X simplemente desplaza todos los bits X lugares hacia la izquierda, es fácil ver que cualquier entero debe tener todos los bits en la mantisa que terminan a la derecha del punto decimal en cero.
Cualquier entero excepto cero tiene la siguiente forma en binario:
1x ... x donde las x -es representan los bits a la derecha de la MSB (bit más significativo).
Debido a que excluimos el cero, siempre habrá un MSB que es uno, y por eso no está almacenado. Para almacenar el número entero, debemos llevarlo a la forma antes mencionada: -1 signo × 1.mantissa × 2 exponente - sesgo .
Eso es lo mismo que mover los bits sobre el punto decimal hasta que solo haya el MSB hacia la izquierda del MSB. Todos los bits a la derecha del punto decimal se almacenan en la mantisa.
A partir de esto, podemos ver que podemos almacenar como máximo 52 dígitos binarios aparte del MSB.
Se sigue que el número más alto donde todos los bits se almacenan explícitamente es
111(omitted)111. that''s 53 ones (52 + implicit 1) in the case of doubles.
Para esto, necesitamos establecer el exponente, de modo que el punto decimal se desplace 52 lugares. Si tuviéramos que aumentar el exponente en uno, no podemos saber el dígito derecho a la izquierda después del punto decimal.
111(omitted)111x.
Por convención, es 0. Configurando toda la mantisa a cero, recibimos el siguiente número:
100(omitted)00x. = 100(omitted)000.
Eso es un 1 seguido de 53 ceros, 52 almacenados y 1 agregado debido al exponente.
Representa 2 53 , que marca el límite (tanto negativo como positivo) entre el cual podemos representar con precisión todos los números enteros. Si quisiéramos agregar uno a 2 53 , tendríamos que establecer el cero implícito (denotado por la x
) en uno, pero eso es imposible.
El módulo de matemáticas de Python contiene funciones prácticas como floor
y ceil
. Estas funciones toman un número de punto flotante y devuelven el entero más cercano por debajo o por encima. Sin embargo, estas funciones devuelven la respuesta como un número de coma flotante. Por ejemplo:
import math
f=math.floor(2.3)
Ahora f
regresa:
2.0
¿Cuál es la forma más segura de obtener un entero de este flotante, sin correr el riesgo de errores de redondeo (por ejemplo, si el flotante es equivalente a 1.99999) o quizás debería usar otra función por completo?
Combinando dos de los resultados anteriores, tenemos:
int(round(some_float))
Esto convierte un flotador en un número entero bastante confiable.
Otra muestra de código para convertir un real / float a un entero usando variables. "vel" es un número real / flotante y se convierte al siguiente INTEGER más alto, "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))
Podría usar la función de ronda. Si no usa un segundo parámetro (# de dígitos significativos), entonces creo que obtendrá el comportamiento que desea.
Salida IDLE.
>>> round(2.99999999999)
3
>>> round(2.6)
3
>>> round(2.5)
3
>>> round(2.4)
2
Si necesita convertir un flotador de cuerda en un int, puede usar este método.
Ejemplo: ''38.0''
a 38
Para convertir esto a un int, puede convertirlo en un float y luego en un int. Esto también funcionará para cadenas float o cadenas enteras.
>>> int(float(''38.0''))
38
>>> int(float(''38''))
38
Nota : Esto eliminará cualquier número después del decimal.
>>> int(float(''38.2''))
38
Todos los enteros que pueden representarse mediante números de coma flotante tienen una representación exacta. Entonces puede usar int
manera segura en el resultado. Las representaciones inexactas ocurren solo si estás tratando de representar un número racional con un denominador que no es una potencia de dos.
¡Que esto funcione no es trivial en absoluto! Es una propiedad de la representación de punto flotante IEEE que int∘floor = ⌊⋅⌋ si la magnitud de los números en cuestión es lo suficientemente pequeña, pero son posibles diferentes representaciones donde int (piso (2.3)) podría ser 1.
Para citar de Wikipedia ,
Cualquier entero con valor absoluto menor que o igual a 2 24 puede representarse exactamente en el formato de precisión simple, y cualquier entero con valor absoluto menor o igual a 2 53 puede representarse exactamente en el formato de doble precisión.
Use int(your non integer number)
lo clavará.
print int(2.3) # "2"
print int(math.sqrt(5)) # "2"
math.floor
siempre devolverá un número entero y, por lo tanto, int(math.floor(some_float))
nunca introducirá errores de redondeo.
Sin embargo, es posible que el error de redondeo ya se haya introducido en math.floor(some_large_float)
, o incluso cuando se almacena un número grande en un float en primer lugar. (Los números grandes pueden perder precisión cuando se almacenan en flotadores).