2016-03-10 14 views
12

Używam python3 z numpy w wersji 1.8.2 (ten sam problem z numpy 1.10.4 i python2) i próbuję zrobić coś bardzo prostego: mnożenie dwóch liczb całkowitych.numpy.int64 razy int -> numpy.float64

import numpy as np 
a = 9223372036854775808 
type(a) 
b = np.int64(0) 
type(b) 
type(b*a) 

wyjście jest jednak:

builtins.int 
numpy.int64 
numpy.float64 

więc mnożenie dwóch liczb całkowitych zwraca pływaka! Czy istnieje uzasadnione wytłumaczenie tego?

Należy pamiętać, że jeśli zmieni się

a = 9223372036854775807 
type(b*a) 

zwrotów

numpy.int64 

A gdybym podnieść go do

a = 92233720368547758100 
type(b*a) 

zwrotów (w python3)

builtins.int 

oraz (w python2)

long 

Jak rozumiem że musi być jakiś przepełnienie, ale dlaczego?

+2

* Czy istnieją jakieś rozsądne wytłumaczenie dla niego * Tak, jest to obsługa zakresu wartości zasięgu. – wallyk

+0

Rozumiem, ale wydaje mi się dziwne, że typ jest poprawnie rzucany na długo, gdy liczba całkowita jest zwiększona do 92233720368547758100. Czy więc "długi" jest jedynym bezpiecznym sposobem na obsługę długich liczb? –

+2

Z dokumentacji https://docs.python.org/2/library/stdtypes.html#numeric-tites-int-float-long-complex, ** Długie liczby całkowite mają nieograniczoną precyzję. ** Prawdopodobnie jest to wybór efektywności : pływaki mają ograniczoną precyzję i zasięg, ale są one szybkie obliczeniowo. Nieograniczona precyzja Longs może być bardzo kosztowna w arytmetyce, więc rzucanie jest uzasadnione, aby wyraźnie poprosić o taką kompromis. – wallyk

Odpowiedz

1

W rzeczywistości jest to bardzo dobra obserwacja i pytanie. Oto szybkie analogia:

import numpy as np 

a = 9223372036854775808 

pamiętać, że są przekroczeniu limitu int, że wkracza w zakres long int

a będzie produkować moc jak 9223372036854775808L

type(a) będzie produkować wyjście jako <type 'long'>

W poniższym przypadku, przebywają ze w limicie int

a = 9223372036854775807 

Tutaj a wyjście powraca jako 9223372036854775807

typ (a) zwraca wyjście jako <type 'int'>

załóżmy b = np.int64(1) na przykład. opiszę w podczas dlaczego wziąłem np.int64(1) zamiast np.int64(0)

b*a zwrotów 9.2233720368547758e+18, jak widać jest ona reprezentowana w dziesiętnych w postaci Eulera.

type(b*a) powraca np.float64

Stąd Z tego też powodu, jest on przekształcany do unoszenia tj np.float (64). Eulers formą liczby zawsze musi pływaka/punkty dziesiętne dla swojej reprezentacji

powód do uznania b jak np.int64(1): Gdyby to było np.int64(0), nigdy nie zauważy wyjście jako wynik będzie wszystkie 0s

0

Ta odpowiedź nie jest naprawdę odpowiedź: jest próbą lepszego zrozumienia problemu!

Pythona 2.7.13 Mam

In [24]: a = 9223372036854775808; type(a) 
Out[24]: long 

Choć w python 3.6.0 Mam

In [24]: a = 9223372036854775808; type(a) 
Out[24]: int 

I to jest spójne z tym, że długo jeszcze nazwie int nawet jeśli zachowuje się jak długo w Python3.

Czy może to być częścią problemu zgłoszonego błędu? Jeśli pozostaniemy w Python2, czy to, co zobaczysz, może być błędem numpy w zapytaniu o typ wartości przechowywanej w zmiennej podczas wykonywania mnożenia? Rozważ

In [11]: type(int(9223372036854775807)) 
Out[11]: int 

In [12]: type(int(9223372036854775808)) 
Out[12]: long 


In [13]: a = 9223372036854775808 

In [14]: b = np.int64(0) 

In [15]: type(9223372036854775808 * np.int64(0)) 
Out[15]: long 

In [16]: type(b*a) 
Out[16]: numpy.float64 

In [17]: type(long(9223372036854775808) * np.int64(0)) 
Out[17]: long 

In [18]: type(int(9223372036854775808) * np.int64(0)) 
Out[18]: long 

In [19]: type(np.int64(9223372036854775808) * np.int64(0)) 
--------------------------------------------------------------------------- 
OverflowError        Traceback (most recent call last) 
<ipython-input-18-93a64125698a> in <module>() 
----> 1 type(np.int64(9223372036854775808) * np.int64(0)) 

OverflowError: Python int too large to convert to C long 

Liczba 9223372036854775808 są przechowywane tak długo.

Linia 15 procesor mówi "długie czasy int64 jest długi, ponieważ jest to największy kontener".

Linia 16 procesor widzi jako int i powiedział „int razy np.int64 jest np.int64 jako wolę przechowywać go w rodzaju numpy, ponieważ to nazwać, ale czekać ... 9223372036854775808 nie może pozostać w int64, więc mam teraz kłopoty (nieoczekiwane kłopoty, jak to się nie dzieje, gdy używam tylko typu numpy - wiersz 19). Następnie ustawiłem się w "trybie awaryjnym" przechowując wyniki domyślnie w największym pojemniku numpy jaki mam, który jest float64 ".

w liniach Python3 15 i 16 zachowuje się inaczej: numpy idzie zawsze w trybie „trouble” jak długo typ jest zawsze wykrywany jako int:

In [10]: type(9223372036854775808 + np.int64(0)) 
Out[10]: numpy.float64 

In [11]: type(a*b) 
Out[11]: numpy.float64 
Powiązane problemy