Difference between revisions of "Numpy surprises"
From Tech
Jump to navigationJump to search| (5 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
| − | New in numpy version 2: numpy int types aren't promoted to bigger types |
+ | New in numpy version 2: numpy int types aren't promoted to bigger types in operations that involve a python int: |
| − | >>> np. |
+ | >>> np.__version__ |
| ⚫ | |||
| + | # |
||
| ⚫ | |||
<python-input-21>:1: RuntimeWarning: overflow encountered in scalar add |
<python-input-21>:1: RuntimeWarning: overflow encountered in scalar add |
||
np.uint8(0) |
np.uint8(0) |
||
# |
# |
||
| + | # When the value of the int is bigger than would fit in the numpy type, an error is thrown: |
||
| ⚫ | |||
| + | np.uint8(0)+256 |
||
| ⚫ | |||
| + | Traceback (most recent call last): |
||
| + | File "<python-input-29>", line 1, in <module> |
||
| + | np.uint8(0)+256 |
||
| + | 17:13, 11 December 2025 (CET)17:13, 11 December 2025 (CET)~^[[User:Joosteto|Joosteto]] ([[User talk:Joosteto|talk]]) |
||
| + | OverflowError: Python integer 256 out of bounds for uint8 |
||
| + | |||
| + | |||
| + | |||
The old numpy 1.24 used to promote numpy int types to 64-bit: |
The old numpy 1.24 used to promote numpy int types to 64-bit: |
||
| ⚫ | |||
| ⚫ | |||
| + | '1.24.2' |
||
| + | # |
||
| + | type(np.uint8(1) + 1) |
||
<class 'numpy.int64'> |
<class 'numpy.int64'> |
||
| + | #or to bigger types, if needed |
||
| ⚫ | |||
| + | type(np.uint8(1)+2**63) |
||
| + | <class 'numpy.ulonglong'> |
||
| + | |||
| + | |||
| + | |||
| + | Also funny: the old 1.24 numpy 'promoted' the uint64 type to float when confronted with python int: |
||
| + | |||
| + | np.uint64(1)+1 |
||
| + | 2.0 |
||
| + | type(np.uint64(1)+1) |
||
| + | <class 'numpy.float64'> |
||
| + | # |
||
| + | #But... uin32 isn't promoted to float, but to... int64(!) |
||
| + | type(np.uint32(1)+1) |
||
| + | <class 'numpy.int64'> |
||
| + | # |
||
| + | # Same as uint8: |
||
| + | type(np.uint8(1)+1) |
||
| + | <class 'numpy.int64'> |
||
| + | # |
||
| + | # However, the signed versions, numpy.int64, numpy.int32 are just always converted to numpy.int64: |
||
| + | type(np.int32(1)+1) |
||
| + | <class 'numpy.int64'> |
||
| + | # |
||
| ⚫ | |||
'1.24.2' |
'1.24.2' |
||
| + | |||
| + | |||
| + | This is all improved a lot in numpy 2: |
||
| + | |||
| + | type(np.uint64(1)+1) |
||
| + | <class 'numpy.uint64'> |
||
| + | # |
||
| + | type(np.uint32(1)+1) |
||
| + | <class 'numpy.uint32'> |
||
| + | # |
||
| + | type(np.int32(1)+1) |
||
| + | <class 'numpy.int32'> |
||
| + | # |
||
| + | np.__version__ |
||
| + | '2.2.4' |
||
| + | |||
| + | And without warning/exception: |
||
| + | |||
| + | 2**np.int8(8) |
||
| + | np.int8(0) |
||
| + | # |
||
| + | np.__version__ |
||
| + | '2.2.4' |
||
Latest revision as of 09:01, 16 December 2025
New in numpy version 2: numpy int types aren't promoted to bigger types in operations that involve a python int:
>>> np.__version__
'2.2.4'
#
np.uint8(1) + 255
<python-input-21>:1: RuntimeWarning: overflow encountered in scalar add
np.uint8(0)
#
# When the value of the int is bigger than would fit in the numpy type, an error is thrown:
np.uint8(0)+256
Traceback (most recent call last):
File "<python-input-29>", line 1, in <module>
np.uint8(0)+256
17:13, 11 December 2025 (CET)17:13, 11 December 2025 (CET)~^Joosteto (talk)
OverflowError: Python integer 256 out of bounds for uint8
The old numpy 1.24 used to promote numpy int types to 64-bit:
np.__version__ '1.24.2' # type(np.uint8(1) + 1) <class 'numpy.int64'> #or to bigger types, if needed type(np.uint8(1)+2**63) <class 'numpy.ulonglong'>
Also funny: the old 1.24 numpy 'promoted' the uint64 type to float when confronted with python int:
np.uint64(1)+1 2.0 type(np.uint64(1)+1) <class 'numpy.float64'> # #But... uin32 isn't promoted to float, but to... int64(!) type(np.uint32(1)+1) <class 'numpy.int64'> # # Same as uint8: type(np.uint8(1)+1) <class 'numpy.int64'> # # However, the signed versions, numpy.int64, numpy.int32 are just always converted to numpy.int64: type(np.int32(1)+1) <class 'numpy.int64'> # np.__version__ '1.24.2'
This is all improved a lot in numpy 2:
type(np.uint64(1)+1) <class 'numpy.uint64'> # type(np.uint32(1)+1) <class 'numpy.uint32'> # type(np.int32(1)+1) <class 'numpy.int32'> # np.__version__ '2.2.4'
And without warning/exception:
2**np.int8(8) np.int8(0) # np.__version__ '2.2.4'