Numping casting float32 to float64

I want to do some standard operations on numpy float32

arrays in python 3, however I see strange behavior when working with numpy sum()

. Here's an example session:

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')

      

Any reason why adding a scalar to the result of a sum (which seems to have dtype

of float32

) will return it to float64

? To be clear, I know that I can explicitly pass a scalar in float32

, however, as the last line shows, numpy still respects float32

when adding a scalar to an array. Any explanations or suggestions on how to keep things like float32

without explicit casting?

0


source to share


1 answer


The result np.sum(a)

is a NumPy scalar, not an array. Operations involving only scalars use different casting rules from operations involving (positive-dimensional) NumPy arrays described in the docs for numpy.result_type

.

When an operation includes only scalars (including 0-dimensional arrays), the dtype result is determined solely by the input dtypes. The same is true for operations involving only (positive-dimensional) arrays.

However, when scalars and (positive-sized) arrays are mixed, instead of using actual scalar types, NumPy parses the scalar values ​​to see if their "smaller" datatype can use them, then uses that dtype to traverse the type. (Arrays do not go through this process, even if their values ​​are of a smaller type.)

Thus,

np.sum(a)+1

      

is a scalar operation converting 1

to a scalar NumPy dtype int_

(either int32 or int64 depending on the duration size C) and then promoting based on the dtypes of float32 and int32 / int64 but



a+1

      

includes an array, so the dtype is 1

treated as int8 for promotion purposes.

Since float32 cannot store all int32 (or int64) dtype values, NumPy is updated to float64 for the first ad. (float64 cannot store all int64 dtype values, but NumPy won't advance to numpy.longdouble for that.) Since float32 can store all int8 dtype values, NumPy uses float32 for the second ad.

If you are using a number greater than 1, so it doesn't fit int8:

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

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

      

you can see different ad campaigns.

+3


source







All Articles