2010-06-02 9 views
103

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 a:Python division

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

división del flotador no funciona bien:

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

Si cualquiera de los lados de la división se echó a un flotador que funcionará:

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

Cada lado del primer ejemplo se evalúa como int, lo que significa que la respuesta final se convertirá en un int. Como 0.111 es menor que .5, se redondea a 0. No es transparente en mi opinión, pero supongo que así es.

¿Cuál es la explicación?

+1

Ver también: [¿Por qué esta división no funciona en python?] (Http://stackoverflow.com/questions/1787249/why-doesnt-this-division-work-in-python/1787255#1787255) – miku

+1

Adam, todavía no me gusta tu explicación. El primer ejemplo es la división entera, que simplemente devuelve 0. El segundo ejemplo está entre paréntesis incorrectamente para el efecto que desee. –

+0

@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 el problema muy bien, especialmente @KennyTM. Es importante notar 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 división de importación __future__ y usaré el 3 .x comportamiento. Aclamaciones. –

Respuesta

206

Estás usando Python 2.x, donde las divisiones de números enteros se trunca en lugar de convertirse en un número de coma flotante.

>>> 1/2 
0 

Usted debe hacer uno de ellos un float:

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

o from __future__ import division, que las fuerzas / a adoptar un comportamiento de Python 3.x que siempre devuelve un flotador.

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

Si usa 'from __future__ import division' puede obtener el antiguo comportamiento de división de estilo C al usar dos barras inclinadas (por ejemplo,' 1 // 2' dará como resultado 0). Ver [Pep 238 Cómo cambiar el operador de la división] (http://www.python.org/dev/peps/pep-0238/) – User

+0

¿Funciona el operador '//' en Python 2.x? – sam

+0

@sam: consulte el comentario del usuario anterior. – kennytm

10

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

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

@ Adam Nelson: Funciona correctamente para mí. Verifica tus paréntesis. –

+0

En realidad, me equivoco, pero después de mirar los documentos, uno debe echar primero el lado derecho. –

+10

@ Adam: no importa de qué lado primero. – kennytm

0

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

intenta transmitir uno de los operandos de "/" para ser un flotador:

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

Estás echando a flotar después de la división ya ha sucedido en el segundo ejemplo. Prueba esto:

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

Me enteré de que python tiene conversiones, no conversiones. – miku

17

Eres putting Integers in so Python is giving you an integer back:

>>> 10/90 
0 

Si si lanzas a un flotador después el redondeo ya se habrá hecho, en otras palabras, 0 número entero siempre va a ser 0 flotador .

Si usa flotadores en cualquier lado de la división, entonces Python le dará la respuesta esperada.

>>> 10/90.0 
0.1111111111111111 

Así, en su caso:

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

hacer por lo menos uno de ellos flotan, entonces será la división de flotación, no entero:

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

casting el resultado de flotar es demasiado tarde.

2

Especificación de un flotador mediante la colocación de un '' después del número también hará que flote por defecto.

>>> 1/2 
0 

>>> 1./2. 
0.5 
8

Tiene que ver con la versión de python que utiliza. 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 desempeña un papel cuando encasilla.

Ejemplo: Dado que esta es una pregunta que siempre aparece en mi cabeza cuando estoy haciendo operaciones aritméticas (debería convertir a flotar y qué número), se presenta un ejemplo de este aspecto:

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

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

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

Si Typecast el último número entero de flotar, todavía podemos conseguir cero, ya que en el momento en nuestro número se divide por el flotador ya se ha convertido 0 a causa de la división entera.

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

Mismo escenario que el anterior pero cambiando el tipo de flotador un poco más cerca del lado izquierdo.

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

Finalmente, cuando Typecast el primer entero a flotar, el resultado es la deseada, ya que a partir de la primera división, es decir, el extremo izquierdo, utilizamos flotadores.

adicional 1: Si usted está tratando de responder que para mejorar la evaluación de la aritmética, usted debe comprobar this

extra 2: Por favor, tenga cuidado con el siguiente escenario:

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

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

>>>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 enteros.

>>> 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 de enteros en tanto Python 2.7 y Python 3.3.

En Python 2.7 y Python 3.3:

>>>20//15 
1 

Ahora, ver la comparación

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

Para el programa anterior, la salida será falsa en Python 2.7 y Verdadero en Python 3.3.

En Python 2.7 a = 1,75 y b = 1.

En Python 3.3 a = 1,75 y b = 1.75, solo porque / es una división flotante.

+1

Gracias por su respuesta. Me ahorró mucho tiempo. – Jorge

0

Estoy algo sorprendido de que nadie haya mencionado que el cartel original podría haber gustado números racionales para resultar. Si está interesado en esto, el programa basado en Python Sage has your back. (En la actualidad todavía basado en Python 2.x, 3.x, aunque está en marcha.)

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

Esto no es una solución para todos, porque hace hacer algunas preparsing por lo que estos números no son int s, pero Sage Integer elementos de clase. Aún así, vale la pena mencionarlo como parte del ecosistema de Python.

0

Personalmente prefiero insertar un 1. * desde el principio. Así, la expresión se convierta en algo como esto:

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

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

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

por lo imposible sólo tiene que añadir un .0 como 20.0. Y en mi caso, envolver con un float() puede perder un poco de legibilidad.

Cuestiones relacionadas