2012-04-04 12 views
14

Estoy usando la función arange para definir las iteraciones for loop y obtener resultados inesperados.python numpy arange resultados inesperados

i = arange(7.8,8.4,0.05) 
print i 

yeilds lo siguiente:

[ 7.8 7.85 7.9 7.95 8. 8.05 8.1 8.15 8.2 8.25 8.3 8.35 8.4 ] 

sin embargo, utilizando el valor de parada de 8.35 de la siguiente manera

i = arange(7.8,8.35,0.05) 

se obtiene la siguiente

[ 7.8 7.85 7.9 7.95 8. 8.05 8.1 8.15 8.2 8.25 8.3 ] 

Pero yo quiero que mi rango de termina a las 8.35! Sé que puedo usar el valor de parada de> 8.35 y < 8.4 para lograr mi resultado, pero ¿por qué es diferente y en mi opinión, inconsistente?

Editar: Estoy utilizando la versión 2.7

+0

¿Qué versión de Python se utiliza? –

+0

¡Estoy usando 2.7! – smashtastic

+0

Una forma sencilla de evitar estos problemas es utilizar 'arrange = (7.8,8.351,0.05)' – Thiru

Respuesta

9

Tal vez tiene que ver con las limitaciones de números de punto flotante. Debido a la precisión de la máquina, no es posible almacenar todos los valores concebibles perfectamente como un punto flotante. Por ejemplo:

>>> 8.4 
8.4000000000000004 
>>> 8.35 
8.3499999999999996 

Así, 8,4 como punto flotante es ligeramente mayor que el valor real de 8,4, mientras que 8,35 como punto flotante es un poquito menos.

+1

esto parece salir con Python 2.6 pero con 2.7, >>> 8.4 sale como 8.4 – avasal

+3

Así que, eso es interesante. Parece que han cambiado la forma en que se imprimen los flotadores, aunque el número subyacente sigue siendo el mismo (ligeramente incorrecto), que se puede ver comparando los valores hexadecimales de los flotantes en Python 2.6 y 2.7. –

+0

Supongo que esto explica lo que estoy viendo, ¡gracias! – smashtastic

18

supongo que se está viendo los efectos de redondeo de punto flotante.

numpy.arange hace lo mismo que python range: No incluye el "punto final". (Por ejemplo range(0, 4, 2) rendirá [0,2] en lugar de [0,2,4])

Sin embargo, para los pasos de punto flotante, los errores de redondeo son acumulan, y de vez en cuando el último valor realmente incluirá el punto final.

Como se indica en la documentación de arange:

Cuando se utiliza un paso no entero, tal como 0,1, los resultados a menudo no ser coherente. Es mejor usar linspace para estos casos.

numpy.linspace genera un número específico de puntos entre un punto inicial y un punto final. Por cierto, incluye los puntos finales por defecto.

+0

hola - He intentado encontrar los documentos de ayuda en línea para linspace pero está extrañamente en blanco ... ¿tiene un enlace adecuado? ? – smashtastic

+1

http://docs.scipy.org/doc/numpy-1.6.0/reference/generated/numpy.linspace.html Alternativamente, puedes hacer 'pydoc numpy.linspace' o si estás en un intérprete de python' help (numpy.linspace) ', o en' ipython', es simplemente 'numpy.linspace?'. –

+0

eso está claro en los documentos, pero no lo hace numpy.arange útil lo hace? – marbel

3

la ayuda de la función arange dice

For floating point arguments, the length of the result is 
    ``ceil((stop - start)/step)``. Because of floating point overflow, 
    this rule may result in the last element of `out` being greater 
    than `stop`. 

para Python 2.7, conversiones entre los números de punto flotante y cadenas están ahora redondeado correctamente en la mayoría de las plataformas.

en 2,7

>>> float(repr(2.3)) 
2.3 

en 2,6

>>> float(repr(2.3)) 
2.2999999999999998 
1

que tenían el mismo problema y he implementado mi propia función para corregir este problema redondeo con numpy.arange:

import numpy as np 
def my_arange(a, b, dr, decimals=6): 
    res = [a] 
    k = 1 
    while res[-1] < b: 
     tmp = round(a + k*dr,decimals) 
     if tmp > b: 
      break 
     res.append(tmp) 
     k+=1 

    return np.asarray(res) 
+0

esto fue útil. ¡Gracias! – marbel

Cuestiones relacionadas