División de Python


133

Estaba tratando de normalizar un conjunto de números de -100 a 0 a un rango de 10-100 y estaba teniendo problemas solo para notar que, incluso sin ninguna variable, esto no evalúa la forma en que esperaría que:

>>> (20-10) / (100-10)
0

La división de flotación tampoco funciona:

>>> float((20-10) / (100-10))
0.0

Si cualquiera de los lados de la división se lanza a flotación, funcionará:

>>> (20-10) / float((100-10))
0.1111111111111111

Cada lado en el primer ejemplo está evaluando como un int, lo que significa que la respuesta final se lanzará a un int. Como 0.111 es menor que .5, se redondea a 0. En mi opinión, no es transparente, pero supongo que así es.

¿Cuál es la explicación?



3
Adam, todavía no me gusta tu explicación. El primer ejemplo es la división de enteros, que simplemente devuelve 0. El segundo ejemplo está entre paréntesis incorrectamente para el efecto que desea.
Presidente James K. Polk

@GregS El primer ejemplo fue el problema. El segundo ejemplo es explicativo y fue escrito después de la primera pregunta. Todas las respuestas a continuación explican muy bien el problema, especialmente @KennyTM. Es importante tener en cuenta que mi problema original es solo un problema en Python 2.x, no 3. Es un poco desconcertante que el comportamiento cambie de esa manera, pero ahora que lo sé, lo usaré de la futura división de importación y usaré el 3 .x comportamiento. Salud.
Adam Nelson

1
Adam, por favor corrige tu última EDICIÓN. El lado derecho no tiene nada especial; Para que una división sea flotante, el numerador o el denominador (o ambos) deben ser flotantes. Si crees que lees en los documentos que el lado derecho necesita flotar, entonces la documentación está mal redactada y debe corregirse, o la malinterpretaste. ¿Viste un ejemplo, tal vez, y luego extrapolaste una regla?
tzot

Respuestas:


246

Estás utilizando Python 2.x, donde las divisiones enteras se truncarán en lugar de convertirse en un número de coma flotante.

>>> 1 / 2
0

Deberías hacer uno de ellos un float:

>>> float(10 - 20) / (100 - 10)
-0.1111111111111111

o from __future__ import division, que obliga /a adoptar el comportamiento de Python 3.x que siempre devuelve un flotante.

>>> from __future__ import division
>>> (10 - 20) / (100 - 10)
-0.1111111111111111

10
Si lo usa from __future__ import division, puede obtener el antiguo comportamiento de división de estilo C mediante el uso de dos barras diagonales (por ejemplo, 1 // 2dará como resultado 0). Vea Pep 238 Cambiando el operador de la división
Usuario

1
@Usuario No es necesario importar desde __future__. En Python 2 y 3 se //hace referencia __floordiv__()por defecto.
Casimir

21

Estás poniendo números enteros para que Python te devuelva un número entero :

>>> 10 / 90
0

Si después de lanzar esto a un flotante, el redondeo ya se habrá realizado, en otras palabras, 0 entero siempre será 0 flotante.

Si usa flotadores a ambos lados de la división, Python le dará la respuesta que espera.

>>> 10 / 90.0
0.1111111111111111

Entonces en tu caso:

>>> float(20-10) / (100-10)
0.1111111111111111
>>> (20-10) / float(100-10)
0.1111111111111111

11

Necesitas cambiarlo a flotador ANTES de hacer la división. Es decir:

float(20 - 10) / (100 - 10)

44
@ Adam Nelson: funciona correctamente para mí. Revisa tus paréntesis.
Fred Larson

En realidad, me equivoco, pero después de mirar los documentos, primero se debe lanzar el lado derecho.
Adam Nelson

10
@ Adam: No importa de qué lado primero.
kennytm

11

En Python 2.7, el /operador es una división entera si las entradas son enteras:

>>>20/15
1

>>>20.0/15.0
1.33333333333

>>>20.0/15
1.33333333333

En Python 3.3, el /operador es una división flotante incluso si las entradas son enteras.

>>> 20/15
1.33333333333

>>>20.0/15
1.33333333333

Para la división de enteros en Python 3, utilizaremos el //operador.

El //operador es un operador de división entera en Python 2.7 y Python 3.3.

En Python 2.7 y Python 3.3:

>>>20//15
1

Ahora, mira la comparación

>>>a = 7.0/4.0
>>>b = 7/4
>>>print a == b

Para el programa anterior, la salida será False en Python 2.7 y True en Python 3.3.

En Python 2.7 a = 1.75 yb = 1.

En Python 3.3 a = 1.75 yb = 1.75, solo porque /es una división flotante.


8

Tiene que ver con la versión de Python que usas. Básicamente adopta el comportamiento C: si divide dos enteros, los resultados se redondearán a un entero. También tenga en cuenta que Python realiza las operaciones de izquierda a derecha, lo que juega un papel cuando escribe.

Ejemplo: dado que esta es una pregunta que siempre aparece en mi cabeza cuando estoy haciendo operaciones aritméticas (si debo convertir a flotante y qué número), se presenta un ejemplo de ese aspecto:

>>> a = 1/2/3/4/5/4/3
>>> a
0

Cuando dividimos enteros, no sorprende que se redondee más bajo.

>>> a = 1/2/3/4/5/4/float(3)
>>> a
0.0

Si escribimos el último número entero para flotar, todavía obtendremos cero, ya que para cuando nuestro número se divida entre el flotador ya se ha convertido en 0 debido a la división del entero.

>>> a = 1/2/3/float(4)/5/4/3
>>> a
0.0

El mismo escenario que el anterior pero desplazando el tipo de letra flotante un poco más cerca del lado izquierdo.

>>> a = float(1)/2/3/4/5/4/3
>>> a
0.0006944444444444445

Finalmente, cuando escribimos el primer número entero para flotar, el resultado es el deseado, ya que comenzando desde la primera división, es decir, la más a la izquierda, usamos flotantes.

Extra 1: Si está tratando de responder eso para mejorar la evaluación aritmética, debe verificar esto

Extra 2: Tenga cuidado con el siguiente escenario:

>>> a = float(1/2/3/4/5/4/3)
>>> a
0.0

4

Especificar un flotador colocando un '.' después de que el número también hará que flote por defecto.

>>> 1 / 2
0

>>> 1. / 2.
0.5

2

Haga que al menos uno de ellos flote, entonces será división de flotación, no entero:

>>> (20.0-10) / (100-10)
0.1111111111111111

Lanzar el resultado para flotar es demasiado tarde.


1

En python cv2no se actualiza el cálculo de división. Por lo tanto, debe incluir from __future__ import division en la primera línea del programa.


0

De cualquier manera, es una división entera. 10/90 = 0. En el segundo caso, simplemente estás lanzando 0 a un flotador.

Intenta lanzar uno de los operandos de "/" para que sea flotante:

float(20-10) / (100-10)

0

Estás lanzando para flotar después de que la división ya haya sucedido en tu segundo ejemplo. Prueba esto:

float(20-10) / float(100-10)

0

Estoy algo sorprendido de que nadie haya mencionado que el póster original podría haber querido que resultaran números racionales . Si está interesado en esto, el programa basado en Python Sage le respalda . (Actualmente todavía se basa en Python 2.x, aunque 3.x está en marcha).

sage: (20-10) / (100-10)
1/9

Esta no es una solución para todos, ya que hace algunos preparativos, por lo que estos números no son ints, sino Integerelementos de clase Sage . Aún así, vale la pena mencionarlo como parte del ecosistema Python.


0

Personalmente, preferí insertar un 1. *al principio. Entonces la expresión se convierte en algo así:

1. * (20-10) / (100-10)

Como siempre hago una división para alguna fórmula como:

accuracy = 1. * (len(y_val) - sum(y_val)) / len(y_val)

así que es imposible simplemente agregar un me .0gusta 20.0. Y en mi caso, envolverlo con un float()puede perder un poco de legibilidad.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.