The dtype
np.uint8
represents an unsigned integer in 8 bits. Its value may therefore be in the range $0 - 255$. Explain the following behaviour:
In [x]: x = np.uint8(250)
In [x]: x*2
Out[x]: 500
In [x]: x = np.array([250,], dtype=np.uint8)
In [x]: x*2
Out[x]: array([244], dtype=uint8)
In the first case, a single object is created of the requested dtype
and multiplied by a scalar (regular Python int
). Python "upcasts" to return the result in dtype
that can hold it:
In [x]: x = np.uint8(250)
In [x]: type(x*2)
Out[x]: numpy.int64
However, a ndarray
, because it has a fixed byte-size, cannot be upcast in the same way: its own dtype
takes precedence over that of the scalar multiplying it and so the multiplication is carried out modulo 256.
Compare this with the result of multiplying two scalars with the same dtype
:
In [x]: np.uint8(250) * np.uint8(2)
Out[x]: 244 # (of type np.uint8)
(You may also see a warning: RuntimeWarning: overflow encountered in ubyte_scalars
.)