import numpy as np arr_int = np.array([1, 2, 3], dtype=np.int8) arr_float = np.array([1.0, 2.0, 3.0], dtype=np.float64) sum_arr = arr_int + arr_float print(sum_arr) print(sum_arr.dtype)
When adding arrays of different dtypes, NumPy upcasts to the more general dtype to avoid data loss. Here, int8 is upcast to float64, so the result is float64.
import numpy as np arr_small = np.ones(1_000_000, dtype=np.int8) arr_large = np.ones(1_000_000, dtype=np.int64) print(arr_small.nbytes) print(arr_large.nbytes)
int8 uses 1 byte per element, so 1 million elements use 1,000,000 bytes. int64 uses 8 bytes per element, so 1 million elements use 8,000,000 bytes.
import numpy as np import time arr1 = np.ones(1000000, dtype=np.float32) arr2 = np.ones(1000000, dtype=np.float64) start = time.time() for _ in range(100): result = arr1 + arr2 end = time.time() print(end - start)
Adding float32 and float64 arrays causes the float32 array to be upcast to float64 each time, which uses more memory and CPU cycles, slowing down the operation.
Using smaller dtypes means less memory per element, so more data fits in CPU cache. This reduces memory access time and speeds up vectorized operations.
Values up to 1000 fit in unsigned 16-bit integers (0 to 65535). Using np.uint16 uses 2 bytes per element, saving memory compared to int32 or float64, and avoids data loss unlike int8.