int0 - python numpy convert dtype



Numping casting float32 to float64 (1)

Я хочу выполнить некоторые стандартные операции с numpy массивами float32 в python 3, однако я вижу странное поведение при работе с numpy sum() . Вот пример сеанса:

Python 3.6.1 |Anaconda 4.4.0 (x86_64)| (default, May 11 2017, 13:04:09) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin

import numpy as np
np.__version__
Out[3]: '1.12.1'
a = np.ones(10).astype(np.float32)
np.sum(a).dtype
Out[5]: dtype('float32')
(np.sum(a)+1).dtype
Out[6]: dtype('float64')
(np.sum(a)+1.).dtype
Out[7]: dtype('float64')
(a+1).dtype
Out[8]: dtype('float32')

Любая причина, почему добавление скаляра в результат суммы (которая, кажется, имеет dtype of float32 ), вернет ее обратно в float64 ? Чтобы быть ясным, я знаю, что я могу явно float32 скаляр в float32 , однако, как показывает последняя строка, numpy по-прежнему уважает float32 при добавлении скаляра в массив. Любые объяснения или предложения о том, как хранить вещи как float32 без явного литья?


Результатом np.sum(a) является скаляр NumPy, а не массив. Операции, включающие только скаляры, используют разные правила кастинга из операций с массивами NumPy (положительно-размерными), описанными в документах для numpy.result_type .

Когда операция включает только скаляры (включая 0-мерные массивы), результат dtype определяется исключительно входными дтипами. То же самое верно для операций с участием только (позитивномерных) массивов.

Однако, когда скаляры и (положительно-размерные) массивы смешиваются, вместо использования реальных типов скаляров NumPy проверяет значения скаляров, чтобы увидеть, может ли их «меньший» тип данных использовать их, затем использует этот тип dtype для типа продвижение. (Массивы не проходят этот процесс, даже если их значения будут соответствовать меньшему типу.)

Таким образом,

np.sum(a)+1

является скалярной операцией, преобразующей 1 в скаляр NumPy dtype int_ (либо int32, либо int64 в зависимости от размера C long), а затем выполняет продвижение на основе dtypes float32 и int32 / int64, но

a+1

включает массив, поэтому dtype 1 рассматривается как int8 для целей продвижения по службе.

Поскольку float32 не может хранить все значения dtype int32 (или int64), NumPy обновляется до float64 для первой рекламы. (float64 не может хранить все значения dtype int64, но NumPy не будет продвигать на numpy.longdouble для этого.) Поскольку float32 может хранить все значения dtype int8, NumPy придерживается float32 для второй рекламы.

Если вы используете число больше 1, поэтому он не подходит для int8:

In [16]: (a+1).dtype
Out[16]: dtype('float32')

In [17]: (a+1000000000).dtype
Out[17]: dtype('float64')

вы можете видеть разные рекламные акции.





casting