Numpy: Saída inesperada de arange com dtype = int

Criado em 5 mai. 2020  ·  5Comentários  ·  Fonte: numpy/numpy


Em [3]: np.arange (-3, 0, 0,5, dtipo = int)
Fora [3]: matriz ([- 3, -2, -1, 0, 1, 2])

Bem, ver um "1" e um "2" foi um pouco inesperado para nós, já que ambos os números são um pouco maiores que 0.

Normalmente, este é o resultado sem 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])

O manual numpy afirma:
dtype: dtype
O tipo da matriz de saída. Se dtype não for fornecido, inferir o tipo de dados dos outros argumentos de entrada.

Portanto, deve afetar apenas a matriz de saída, certo?

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))

Mensagem de erro:

Nenhuma mensagem de erro ...

Informações sobre a versão Numpy / Python:

Nós testamos em numpy '1.18.4' (puro Python 3.7.6), bem como '1.18.1' (Anaconda 3.7 com a última atualização aplicada). Mesmo resultado.

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

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

00 - Bug numpy.core

Comentários muito úteis

Obter valores maiores do que "parar" não é nada legal e um pouco inesperado. Se arange não for float, você pode verificar os tipos floaty numpy e gerar uma exceção.

Além disso, a entrada manual para dtype realmente permite que o usuário espere algo como uma conversão de astype (dtype) apenas da saída.

E se:
1.) Exceção para argumentos não inteiros (ou seja, iniciar, parar, passo).
2.) Verifique se stop> = start, caso contrário, gere uma exceção
3.) Elenco start, stop, step to int64 no início da função.
4.) astype (dtype) a saída

Em vez de 1.) você pode redirecionar para linspace dentro de uma faixa se uma entrada não inteira for encontrada.

Todos 5 comentários

Bugs como este são relatados repetidamente. Por razões perdidas no tempo, estou bastante confiante de que a implementação de uma variedade é 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)]

Talvez devêssemos adicionar esse pseudo-código à documentação?

Sim, esse código está correto (mas não tenho 100% de certeza sobre o cálculo de n ). Este exemplo específico é muito extremo e obviamente quebrado, talvez possamos realmente nos livrar dele de alguma forma?

arange é repetidamente odiado pela definição indiscutivelmente quebrada, mas não consigo pensar em uma proposta realmente boa para abordá-la (embora talvez uma tenha surgido antes).
Não é como se pudéssemos mudar bem o comportamento de arange para flutuadores (talvez ajustes de precisão, mas mudanças de ponto final não são boas para IMO). Portanto, precisaríamos criar uma nova função ... Mas, na maioria dos casos, parece-me que linspace é melhor do que uma matriz flutuante "correta", não tenho certeza se uma matriz flutuante corrigida realmente muitos casos de uso.

No final, acho que gostaria de uma proposta bem pensada: / ...

Obter valores maiores do que "parar" não é nada legal e um pouco inesperado. Se arange não for float, você pode verificar os tipos floaty numpy e gerar uma exceção.

Além disso, a entrada manual para dtype realmente permite que o usuário espere algo como uma conversão de astype (dtype) apenas da saída.

E se:
1.) Exceção para argumentos não inteiros (ou seja, iniciar, parar, passo).
2.) Verifique se stop> = start, caso contrário, gere uma exceção
3.) Elenco start, stop, step to int64 no início da função.
4.) astype (dtype) a saída

Em vez de 1.) você pode redirecionar para linspace dentro de uma faixa se uma entrada não inteira for encontrada.

Ei, eu sou um iniciante completo na contribuição de código aberto. Pensei em tentar. Que tal este trecho? @ eric-wieser

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

Bugs como este são relatados repetidamente. Por razões perdidas no tempo, estou bastante confiante de que a implementação de uma variedade é 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)]
Esta página foi útil?
0 / 5 - 0 avaliações