#python #arrays #biginteger #square
Вопрос:
import numpy as np
a = np.arange(1000000).reshape(1000,1000)
print(a**2)
С помощью этого кода я получаю такой ответ. Почему я получаю отрицательные значения?
[[ 0 1 4 ..., 994009 996004 998001]
[ 1000000 1002001 1004004 ..., 3988009 3992004 3996001]
[ 4000000 4004001 4008004 ..., 8982009 8988004 8994001]
...,
[1871554624 1873548625 1875542628 ..., -434400663 -432404668 -430408671]
[-428412672 -426416671 -424420668 ..., 1562593337 1564591332 1566589329]
[1568587328 1570585329 1572583332 ..., -733379959 -731379964 -729379967]]
Ответ №1:
На вашей платформе np.arange возвращает массив dtype ‘int32’ :
In [1]: np.arange(1000000).dtype
Out[1]: dtype('int32')
Каждый элемент массива является 32-разрядным целым числом. Возведение в квадрат приводит к результату, который не укладывается в 32-битные значения. Результат обрезается до 32 бит и по-прежнему интерпретируется как 32-разрядное целое число, однако именно поэтому вы видите отрицательные числа.
Изменить: В этом случае вы можете избежать переполнения целых чисел, построив массив dtype ‘int64’ перед возведением в квадрат:
a=np.arange(1000000,dtype='int64').reshape(1000,1000)
Обратите внимание, что обнаруженная вами проблема представляет собой неотъемлемую опасность при работе с numpy. Вы должны тщательно выбирать типы dtypes и заранее знать, что ваш код не приведет к арифметическим переполнениям. Ради скорости numpy не может и не будет предупреждать вас, когда это произойдет.
Видишь http://mail.scipy.org/pipermail/numpy-discussion/2009-April/041691.html для обсуждения этого вопроса в списке рассылки numpy.
Ответ №2:
целые числа python не имеют этой проблемы, так как они автоматически обновляются до длинных целых чисел python при переполнении.
поэтому, если вам удастся переполнить int64, одним из решений является использование python int в массиве numpy:
import numpy
a=numpy.arange(1000,dtype=object)
a**20
Ответ №3:
целочисленные типы numpy имеют фиксированную ширину, и вы видите результаты переполнения целых чисел.
Ответ №4:
Решение этой проблемы заключается в следующем (взято отсюда):
…изменение в классе StringConverter._mapper (numpy/lib/_iotools.py) от:
{{{
_mapper = [(nx.bool_, str2bool, False),
(nx.integer, int, -1),
(nx.floating, float, nx.nan),
(complex, _bytes_to_complex, nx.nan 0j),
(nx.string_, bytes, asbytes('???'))]
}}}
Для
{{{
_mapper = [(nx.bool_, str2bool, False),
(nx.int64, int, -1),
(nx.floating, float, nx.nan),
(complex, _bytes_to_complex, nx.nan 0j),
(nx.string_, bytes, asbytes('???'))]
}}}
Это решило аналогичную проблему, с которой я столкнулся numpy.genfromtxt
для себя
Обратите внимание, что автор описывает это как «временное» и «неоптимальное» решение. Однако у меня не было побочных эффектов при использовании версии 2.0 (пока?!).