Numpy: Salida inesperada de arange con dtype = int

Creado en 5 may. 2020  ·  5Comentarios  ·  Fuente: numpy/numpy


En [3]: np.arange (-3, 0, 0.5, dtype = int)
Fuera [3]: matriz ([- 3, -2, -1, 0, 1, 2])

Bueno, ver un "1" y un "2" fue un poco inesperado para nosotros ya que ambos números son un poco más grandes que 0.

Normalmente, este es el resultado sin dtype = int:

In [2]: np.arange(-3, 0, 0.5)                                                  
Out[2]: array([-3. , -2.5, -2. , -1.5, -1. , -0.5])
and we should get this with dtype=int:
In [4]: np.arange(-3, 0, 0.5).astype(int)                                      
Out[4]: array([-3, -2, -2, -1, -1,  0])

El manual numpy dice:
dtype: dtype
El tipo de matriz de salida. Si no se proporciona dtype, infiera el tipo de datos de los otros argumentos de entrada.

Por lo tanto, solo debería afectar la matriz de salida, ¿verdad?

import numpy as np
print(np.arange(-3, 0, 0.5))
print(np.arange(-3, 0, 0.5, dtype=int))
print(np.arange(-3, 0, 0.5).astype(int))

Mensaje de error:

Sin mensaje de error ...

Información de la versión de Numpy / Python:

Lo probamos bajo numpy '1.18.4' (Python 3.7.6 puro) así como '1.18.1' (Anaconda 3.7 con la última actualización aplicada). Mismo resultado.

1.18.4 3.7.6 (predeterminado, 28 de febrero de 2020, 15:25:38)
[Clang 11.0.0 ( https://github.com/llvm/llvm-project.git eefbff0082c5228e01611f7

1.18.1 3.7.4 (predeterminado, 13 de agosto de 2019, 20:35:49)
[GCC 7.3.0]

00 - Bug numpy.core

Comentario más útil

Obtener valores que son más grandes que "stop" no es realmente agradable y un poco inesperado. Si un rango no es para flotante, puede verificar los tipos de números flotantes y generar una excepción.

Además, la entrada manual para dtype realmente permite al usuario esperar algo como una conversión de astype (dtype) solo de la salida.

Qué tal si:
1.) Excepción para argumentos que no sean enteros (es decir, inicio, parada, paso).
2.) Compruebe si stop> = start, de lo contrario, genere una excepción
3.) Iniciar, detener, pasar a int64 al comienzo de la función.
4.) astype (dtype) la salida

En lugar de 1.) puede redirigir a linspace dentro de un rango si se encuentra una entrada que no sea un número entero.

Todos 5 comentarios

Errores como este se informan una y otra vez. Por razones perdidas en el tiempo, estoy bastante seguro de que la implementación de un rango es algo como:

def arange(start, stop, step, dtype):
    n = (start - stop) // step

    # dtype.type is a cast
    step = dtype.type(start + step) - dtype.type(start)

    # now do what you expect
    return [start + step*i for i in range(n)]

¿Quizás deberíamos agregar ese pseudocódigo a la documentación?

Sí, ese código es correcto (aunque no estoy 100% seguro sobre el cálculo n ). Este ejemplo específico es bastante extremo y, obviamente, está roto, ¿tal vez podamos deshacernos de él de alguna manera?

arange es odiado repetidamente por la definición posiblemente rota, pero no puedo pensar en una propuesta realmente buena para abordarlo (aunque tal vez surgió una antes).
No es como si pudiéramos cambiar bien el comportamiento de arange para los flotadores (tal vez arreglos de precisión, pero los cambios en el punto final no son buenos en mi opinión). Entonces necesitaríamos crear una nueva función ... Pero entonces, en la mayoría de los casos, me parece que linspace es mejor que un rango flotante "correcto", no estoy seguro de que un rango flotante corregido realmente tenga demasiados casos de uso.

Al final, supongo que me gustaría una propuesta bien pensada: / ...

Obtener valores que son más grandes que "stop" no es realmente agradable y un poco inesperado. Si un rango no es para flotante, puede verificar los tipos de números flotantes y generar una excepción.

Además, la entrada manual para dtype realmente permite al usuario esperar algo como una conversión de astype (dtype) solo de la salida.

Qué tal si:
1.) Excepción para argumentos que no sean enteros (es decir, inicio, parada, paso).
2.) Compruebe si stop> = start, de lo contrario, genere una excepción
3.) Iniciar, detener, pasar a int64 al comienzo de la función.
4.) astype (dtype) la salida

En lugar de 1.) puede redirigir a linspace dentro de un rango si se encuentra una entrada que no sea un número entero.

Hola, soy un principiante completo en la contribución de código abierto. Pensé en darle una oportunidad. ¿Qué tal este fragmento? @ eric-wieser

x = []
for i in range(start, stop):
    x.append(i)
    x.append(i+step)
print(np.array(x, dtype))

Errores como este se informan una y otra vez. Por razones perdidas en el tiempo, estoy bastante seguro de que la implementación de un rango es algo como:

def arange(start, stop, step, dtype):
    n = (start - stop) // step

    # dtype.type is a cast
    step = dtype.type(start + step) - dtype.type(start)

    # now do what you expect
    return [start + step*i for i in range(n)]
¿Fue útil esta página
0 / 5 - 0 calificaciones