Хранение больших чисел в массив numpy

у меня есть набор данных, на котором я пытаюсь применить некоторый арифметический метод. Дело в том, что он дает мне относительно большие числа, и когда я делаю это с numpy, они заполняются как 0.

странно то, что когда я вычисляю числа appart, они имеют значение int, они становятся нулями только тогда, когда я вычисляю их с помощью numpy.

x = np.array([18,30,31,31,15])
10*150**x[0]/x[0]
Out[1]:36298069767006890

vector = 10*150**x/x
vector
Out[2]: array([0, 0, 0, 0, 0])

Я, конечно, проверил их типы:

type(10*150**x[0]/x[0]) == type(vector[0])
Out[3]:True

как я могу вычислить эти большие числа, используя numpy, не видя они превратились в нули?

обратите внимание, что если мы удалим фактор 10 в начале проблемы slitghly изменения (но я думаю, что это может быть аналогичная причина):

x = np.array([18,30,31,31,15])
150**x[0]/x[0]
Out[4]:311075541538526549

vector = 150**x/x
vector
Out[5]: array([-329406144173384851, -230584300921369396, 224960293581823801,
   -224960293581823801, -368934881474191033])

отрицательные числа указывают на самые большие числа типа int64 в python, которые были пересечены, не так ли?

2 ответов


Как уже упоминал Нильс Вернер, собственные ctypes numpy не могут сохранять такие большие числа, но сам python может, поскольку объекты int используют реализацию произвольной длины. Так что ты can do-это сказать numpy не преобразовывать числа в ctypes, а вместо этого использовать объекты python. Это будет медленнее, но сработает.

In [14]: x = np.array([18,30,31,31,15], dtype=object)

In [15]: 150**x
Out[15]: 
array([1477891880035400390625000000000000000000L,
       191751059232884086668491363525390625000000000000000000000000000000L,
       28762658884932613000273704528808593750000000000000000000000000000000L,
       28762658884932613000273704528808593750000000000000000000000000000000L,
       437893890380859375000000000000000L], dtype=object)

в этом случае массив numpy будет хранить не сами числа, а ссылки на соответствующие объекты int. Когда вы выполнять арифметические операции они будут выполняться не на массиве numpy, а на объектах за ссылками.
Я думаю, что вы все еще можете использовать большинство функций numpy с этим обходным путем, но они определенно будут намного медленнее, чем обычно.

но это то, что вы получаете, когда имеете дело с такими большими числами :D
Возможно, где-то есть библиотека, которая может справиться с этой проблемой немного лучше.

как раз для завершенности, если точность не проблема, вы также можете использовать поплавки:

In [19]: x = np.array([18,30,31,31,15], dtype=np.float64)

In [20]: 150**x
Out[20]: 
array([  1.47789188e+39,   1.91751059e+65,   2.87626589e+67,
         2.87626589e+67,   4.37893890e+32])

150 ** 28 выходит за рамки того, что может представлять переменная int64 (она находится на стадионе 8e60 в то время как максимально возможное значение unsigned int64 примерно 18e18).

Python может использовать реализацию целого числа произвольной длины, но NumPy этого не делает.

как вы правильно вывели, отрицательные числа являются симптомом переполнения int.