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