Если добавить скаляры float32 и float64, результатом будет float64: float32 повышается до float64.
Однако я обнаружил, что при добавлении массива float32 и скаляра float64 в результате получается массив float32, а не массив float64, как можно было бы ожидать.
Я написал код, воспроизводящий проблему.
Мой вопрос: почему тип dtype np.add(np.array([a]), b)
— float32?
import numpy as np
import sys
print(sys.version_info) # sys.version_info(major=3, minor=10, micro=9, releaselevel='final', serial=0)
print(np.__version__) # '1.24.1'
a = np.float32(1.1)
b = np.float64(2.2)
print((a+b).dtype) # float64
print(np.add(a, np.array([b])).dtype) # float64
print(np.add(np.array([a]), np.array([b])).dtype) # float64
print(np.add(np.array([a]), b).dtype) # float32 ?? expcting float64
Это противоречит документу np.add
(https://numpy.org/doc/stable/reference/generated/numpy.add.html), в котором говорится в примечаниях.
Эквивалентно x1 + x2 с точки зрения широковещательной передачи массива.
x, y = numpy.broadcast_arrays(np.array([a]), b)
print(np.add(x, y).dtype) ## float64
вопрос вынесен в заголовок и отмечен знаком ?? в примере кода
почему dtype n
p.add(np.array([a]), b)
равенfloat32
?
Потому что правила продвижения NumPy, включающие скаляры до NEP 50, были запутанными*. Используя правила NEP 50 в вашей версии NumPy, поведение будет таким, как вы ожидаете:
import numpy as np
import sys
# Use this to turn on the NEP 50 promotion rules
np._set_promotion_state("weak")
print(sys.version_info) # sys.version_info(major=3, minor=10, micro=9, releaselevel='final', serial=0)
print(np.__version__) # '1.24.0'
a = np.float32(1.1)
b = np.float64(2.2)
print((a+b).dtype) # float64
print(np.add(a, np.array([b])).dtype) # float64
print(np.add(np.array([a]), np.array([b])).dtype) # float64
print(np.add(np.array([a]), b).dtype) # float64
Эти правила используются по умолчанию в NumPy 2.0.
*: Точнее, старые правила зависят от значений. Если вы установите a = b = np.finfo(np.float32).max
, результат переполнится, если оставить float32
, поэтому вы получите float64
даже со старыми правилами.
Какой у Вас вопрос ?