Numpy приводит к плаванию python при делении на большое целое число, это ошибка?

#python #arrays #numpy #types #casting

Вопрос:

Вот минимальный пример кода:

 import numpy as np

x = np.array(1e-35, dtype=np.double)
y = int(1e19)
print( type(x/y) )

y = int(1e20)
print( type(x/y) )
 

На моей машине в первом случае он печатается numpy.float64 , а во втором-печатается float . Я предполагаю, что конкретные числа будут отличаться на разных машинах, но дело в том, что для небольших int разделение сохраняет тип, в то время как для больших int тип приводится к плавающей строке Python. Я хотел бы знать, является ли это ошибкой в Numpy или нет, и есть ли какие-либо решения, кроме ручного приведения всего к двойному.

Это кажется безобидным, но когда я пытаюсь написать a ufunc , и приведение происходит только для определенных элементов массива , тип возвращаемого значения становится object , и программа выдает ошибку «не удалось принудительно указать выходной параметр».

Ответ №1:

Тип вывода изменяется, потому int(1e19) что может быть безопасно отлит в an np.int64 , в то время int(1e20) как не может поместиться в an np.int64 и, следовательно, не может быть безопасно отлит (вы можете проверить это с y.bit_length() помощью ). В результате y сначала сохраняется как объект pure-Python (целое число переменного размера), затем Python приводит его к плавающему объекту pure-Python, поэтому результатом также является плавающий объект pure-Python. Это происходит потому, что Numpy пытается применить свои собственные правила семантики, основанные на собственных типах. Когда он не может их использовать (из-за небезопасных/невозможных приведений), применяется резервная объектно-ориентированная семантика на основе чистого Python, приводящая к объектам на основе чистого Python. Тем не менее, это, по-видимому, известная проблема. Вы можете проверить связанные с этим вопросы и обсудить их с разработчиками Numpy на GitHub для получения дополнительной информации.

Я думаю, что лучшая стратегия-не полагаться на такое поведение. Действительно, когда значение с плавающей точкой умножается на огромное целое число, огромное целое число всегда сначала будет приведено к значению с плавающей точкой (из-за правил семантики). Это приведение, вероятно, приведет к потере точности, а также к следующему умножению. Таким образом, я думаю, что лучше привести огромное целое число самостоятельно, чтобы иметь в виду, что целочисленное значение может быть представлено не идеально.