Numpy: np.ceil e np.floor são inconsistentes com math.ceil e math.floor

Criado em 7 mai. 2017  ·  10Comentários  ·  Fonte: numpy/numpy

No Python 3, floor e ceil alterados para retornar números inteiros, em vez de flutuantes:

>>> math.floor(1.5), math.ceil(1.5)
(1, 2)
>>> np.floor(1.5), np.ceil(1.5)
(1.0, 2.0)   # also the output for the first case on 2.7

Devemos atualizar essas funções em numpy para retornar tipos inteiros?

Acho que o caminho da suspensão de uso seria

  • adicione f->i loops ao ufunc, de modo que np.floor(1.5, dtype=int) seja possível
  • no python 3, comece FutureWarning em np.floor(1.5) sem tipo d
  • no python 3, mude o dtype padrão para int
numpy.core

Comentários muito úteis

Como em # 5700, eu voto pelo retorno dos ints. Especialmente agora que numpy é um pouco exigente em exigir ints para índices (o que é bom IMO), ter que converter o valor de retorno de float é muito chato (e gratuitamente requer outro buffer intermediário).

Todos 10 comentários

Essa é uma mudança muito importante que podemos adiar até que abandonemos o suporte para 2.7. Observe que as funções C retornam floats, e as funções C são o que numpy usa. OTOH, inteiros são geralmente o que as pessoas querem e eu considerei adicionar funções ifloor e iceil como versões inteiras no passado. Observe que o Python tem uma vantagem aqui, pois o tipo inteiro tem precisão ilimitada.

O que aconteceria com np.floor([1.5, 1e300]) ? O tipo de int do Python pode ser arbitrariamente longo

O que aconteceria para np.floor ([1.5, 1e300])

A mesma coisa que x = np.array([1.5, 1e300]); np.int64(x) faz faria sentido. Ambos devem provavelmente dar um aviso.

A solução alternativa seria solicitar explicitamente um float, com np.floor(..., dtype=float)

A solução alternativa seria solicitar explicitamente um float, com np.floor(..., dtype=float)

Eu não acho que isso funcione, dada a forma como o envio de ufunc é tratado. Se você tivesse um loop float,float->int , dizer dtype=float seria convertido para int e depois lançado de volta para float, o que não adianta. Mas eu acho que essa é a única maneira de obter o comportamento int-by-default. Você precisaria de ... Duas versões do loop que diferem apenas no tipo de saída e, em seguida, alguma maneira de se certificar de que a versão inteira tem maior "prioridade" do que a versão flutuante. Ou alguma coisa. (Na verdade, pelo que sei, isso é possível organizando cuidadosamente a tabela de pesquisa na ordem certa; o código de envio de loop é complicado. Mas não parece algo em que se possa confiar.)

Eu voto por documentar que np.ceil e np.floor retornam float e pronto. Posso fazer um pedido de pull, se você concordar.

Como em # 5700, eu voto pelo retorno dos ints. Especialmente agora que numpy é um pouco exigente em exigir ints para índices (o que é bom IMO), ter que converter o valor de retorno de float é muito chato (e gratuitamente requer outro buffer intermediário).

Também há algum comportamento surpreendente com as funções Python 3 math.ceil e math.floor , encontradas em HypothesisWorks / hipótese # 1667:

>>> np.dtype('int64').type(2 ** 53 + 1)
9007199254740993
>>> math.ceil(_)
9007199254740992

Assim como nem todos os flutuantes são representáveis ​​como inteiros, os inteiros de 64 bits podem não ser representados como flutuantes - e há um elenco intermediário no método __ceil__ . Não tenho uma solução proposta para isso e não foi difícil descobrir o que está acontecendo, mas mesmo sabendo que np.ceil retorna um float, isso me surpreendeu.

Descobri isto enquanto olhamos para problemas antigos: podemos evitar quebrar a compatibilidade com versões anteriores adicionando novos loops f->i para que pelo menos um possa selecionar a saída inteira? (ou seja, o oposto da sugestão dtype=float acima).

Talvez seja melhor adicionar novas funções, iceil , ifloor , etc. Que flutuadores eventualmente desenvolvam lacunas de tamanho inteiro pode ser um problema, como já apontado. Acho que lidar com isso pode ser complicado se quisermos fazer um pouco melhor no domínio de inteiro.

@charris - sim, talvez seja melhor. Ele poderia então se estender a iround , ifix , etc., também

Esta página foi útil?
0 / 5 - 0 avaliações