Numpy.int64 раз int → numpy.float64
Я использую python3 с numpy версии 1.8.2 (эта же проблема с numpy 1.10.4 и python2) и пытаюсь сделать что-то очень основное: умножая два целых числа.
import numpy as np
a = 9223372036854775808
type(a)
b = np.int64(0)
type(b)
type(b*a)
Выход:
builtins.int
numpy.int64
numpy.float64
Таким образом, умножение двух целых чисел возвращает float! Есть ли разумное объяснение?
Обратите внимание, что если я перейду на
a = 9223372036854775807
type(b*a)
возвращает
numpy.int64
И если я подниму его на
a = 92233720368547758100
type(b*a)
возвращает (в python3)
builtins.int
и (в python2)
long
Как я понимаю, должно быть какое-то переполнение, но почему?
Ответы
Ответ 1
На самом деле это очень хорошее наблюдение и вопрос. Вот быстрая аналогия:
import numpy as np
a = 9223372036854775808
Обратите внимание, что вы пересекаете предел int
, он вводит диапазон long int
a
будет выдавать результат как 9223372036854775808L
type(a)
будет выдавать результат как <type 'long'>
В приведенном ниже случае мы остановимся в пределе int
a = 9223372036854775807
Здесь a
возвращает вывод как 9223372036854775807
type (a) возвращает выходные данные как <type 'int'>
допустим, например, b = np.int64(1)
. Я объясню, почему я взял np.int64(1)
вместо np.int64(0)
b*a
возвращает 9.2233720368547758e+18
, как вы видите, он представлен десятичными знаками в форме Эйлера.
type(b*a)
возвращает np.float64
Следовательно, по вышеуказанной причине он преобразуется в float, то есть np.float(64). Форма Эйлера числа всегда требует плавающих/десятичных точек для ее представления
Причина рассмотрения b
как np.int64(1)
: если он был np.int64(0)
, вы никогда не заметите результат, так как результатом будет все 0s
Ответ 2
Этот ответ на самом деле не является ответом: попытка попытаться лучше понять проблему!
С Python 2.7.13 я получил
In [24]: a = 9223372036854775808; type(a)
Out[24]: long
Пока в python 3.6.0 я получил
In [24]: a = 9223372036854775808; type(a)
Out[24]: int
И это согласуется с тем, что long по-прежнему называется int, даже если он ведет себя так же долго в Python3.
Может ли это быть частью проблемы сообщаемой ошибки? Если мы останемся на Python2, может ли то, что вы видели, быть ошибкой numpy в запросе типа значения, хранящегося в переменной при выполнении умножения?
Рассмотрим
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
Число 9223372036854775808 хранится так долго.
В строке 15 процессор говорит: "Длинные времена int64 длинны, поскольку это самый большой контейнер".
Строка 16 процессор видит как int и говорит, что "int times np.int64 - это np.int64, поскольку я предпочитаю хранить его в виде numpy, поскольку вы его вызываете, но подождите... 9223372036854775808 не может оставаться в int64, поэтому я сейчас в беде (непредвиденная проблема, поскольку это не происходит при использовании только numpy-типа - строка 19). Затем я попал в" проблемный режим ", сохраняя результаты по умолчанию в самом большом контейнере с емкостью, который у меня есть, который является float64".
В Python3 строки 15 и 16 ведут себя по-разному: numpy всегда идет в "режиме тревоги", поскольку длинный тип всегда определяется как int:
In [10]: type(9223372036854775808 + np.int64(0))
Out[10]: numpy.float64
In [11]: type(a*b)
Out[11]: numpy.float64