Vectorized Arithmetic
Do maths on whole arrays without loops: array with scalar, array with array, the element-wise rule and the same-shape requirement.
The IPL wants to add 10 bonus runs to every score, or find each match's partnership total of Virat and Rohit. With a Python list you would write a for loop. With NumPy you write one expression — virat + 10 or virat + rohit — and NumPy does the loop for you in fast compiled C code. This idea is called vectorization, and it is the single most important reason NumPy exists.
Definition
Vectorized arithmetic means applying an arithmetic operator (
+ - * / // % **) to whole arrays at once. The operation is element-wise: elementiof the result is computed only from elementiof each input. With a scalar, the scalar is used with every element; with two arrays, they must have the same shape (or shapes compatible under broadcasting).
- Whole arrays at once — no Python
forloop in your code; NumPy runs a loop internally in C. - Element-wise — position
[i](or[i, j]in 2D) of the result comes from position[i]of the inputs, nothing else. It is not matrix multiplication. - Scalar — a single number such as
10; it is "stretched" to every element (the simplest case of broadcasting). - Same shape — two arrays of shapes
(14,)and(14,)work;(3,)and(2,)fail with aValueError. (Arrays of different but compatible shapes are covered in the Broadcasting chapter.)
Syntax — the arithmetic operators
python
arr + x arr - x arr * x arr / x
arr // x arr % x arr ** x -arr
arr += x # in-place version (also -=, *=, /=, ...)| Operator | Meaning | Same as ufunc | Result dtype for two int arrays |
|---|---|---|---|
+ | add | np.add | int |
- | subtract | np.subtract | int |
* | multiply (element-wise) | np.multiply | int |
/ | true division | np.divide | always float64 |
// | floor division | np.floor_divide | int |
% | remainder (modulo) | np.mod | int |
** | power | np.power | int |
-a | negate | np.negative | int |
x can be a scalar or an array of the same shape as arr.
Example — array with a scalar
python
import numpy as np
virat = np.array([72, 45, 88, 31, 64, 0, 103, 52, 19, 77, 41, 93, 28, 66])
rohit = np.array([56, 0, 74, 88, 32, 45, 61, 17, 90, 38, 72, 5, 83, 49])
print("virat + 10 :", virat + 10)
print("virat * 2 :", virat * 2)
print("virat / 10 :", virat / 10)
print("virat // 10:", virat // 10)
print("virat % 10 :", virat % 10)
print("virat ** 2 :", virat[:5] ** 2)text
virat + 10 : [ 82 55 98 41 74 10 113 62 29 87 51 103 38 76]
virat * 2 : [144 90 176 62 128 0 206 104 38 154 82 186 56 132]
virat / 10 : [ 7.2 4.5 8.8 3.1 6.4 0. 10.3 5.2 1.9 7.7 4.1 9.3 2.8 6.6]
virat // 10: [ 7 4 8 3 6 0 10 5 1 7 4 9 2 6]
virat % 10 : [2 5 8 1 4 0 3 2 9 7 1 3 8 6]
virat ** 2 : [5184 2025 7744 961 4096]How it works: the scalar is combined with every element. / always returns floats (7.2, 10.3), even when both inputs are integers. // drops the decimal part (rounds towards minus infinity) and % gives the remainder — virat // 10 is "how many tens", virat % 10 is "the last digit".
Example — array with array (element-wise)
python
virat = np.array([72, 45, 88, 31, 64, 0, 103, 52, 19, 77, 41, 93, 28, 66])
rohit = np.array([56, 0, 74, 88, 32, 45, 61, 17, 90, 38, 72, 5, 83, 49])
partnership = virat + rohit
difference = virat - rohit
print("Partnership :", partnership)
print("Virat-Rohit :", difference)
print("Match 1 check:", virat[0], "+", rohit[0], "=", partnership[0])
print("Shapes:", virat.shape, rohit.shape, partnership.shape)text
Partnership : [128 45 162 119 96 45 164 69 109 115 113 98 111 115]
Virat-Rohit : [ 16 45 14 -57 32 -45 42 35 -71 39 -31 88 -55 17]
Match 1 check: 72 + 56 = 128
Shapes: (14,) (14,) (14,)How it works: position 0 of the result is virat[0] + rohit[0], position 1 is virat[1] + rohit[1], and so on. The result has the same shape as the inputs.
The element-wise rule in 2D
text
runs (3, 6) balls (3, 6) runs / balls * 100
[[72 45 88 ...] / [[48 32 55 ...] = [[150. 140.6 160. ...]
[56 0 74 ...] [39 0 50 ...] [143.6 nan 148. ...]
[45 32 0 ...]] [31 24 0 ...]] [145.2 133.3 nan ...]]
result[i, j] = runs[i, j] / balls[i, j] * 100 for EVERY i, j at oncepython
runs = np.array([
[72, 45, 88, 31, 64, 0], # Virat
[56, 0, 74, 88, 32, 45], # Rohit
[45, 32, 0, 67, 18, 54], # Hardik
])
balls = np.array([
[48, 32, 55, 24, 41, 0],
[39, 0, 50, 56, 25, 33],
[31, 24, 0, 46, 15, 38],
])
strike_rate = runs[:, 3:5] / balls[:, 3:5] * 100 # matches 4-5: nobody faced 0 balls
print(strike_rate.round(1))
print("Total runs per match:", runs.sum(axis=0))text
[[129.2 156.1]
[157.1 128. ]
[145.7 120. ]]
Total runs per match: [173 77 162 186 114 99]How it works: runs[:, 3:5] and balls[:, 3:5] are both (3, 2), so every cell is divided by the cell in the same position. We picked matches 4–5 on purpose: in the other matches some player faced 0 balls, and 0/0 gives the special value nan you see in the diagram — that is the topic Errors & Special Values.
Example — shapes must match
python
a = np.array([72, 45, 88])
b = np.array([56, 0])
try:
print(a + b)
except ValueError as e:
print("ValueError:", e)text
ValueError: operands could not be broadcast together with shapes (3,) (2,)How it works: 3 elements cannot be paired with 2 elements, so NumPy refuses instead of guessing. Always check .shape when you get this error.
Example — dtype surprises: in-place ops and overflow
python
scores = np.array([10, 20])
try:
scores += 0.5 # int array cannot hold 10.5
except Exception as e:
print(type(e).__name__, ":", e)
small = np.array([100, 120], dtype=np.int8) # int8 holds -128..127
print(small + small) # wraps around silently!text
UFuncTypeError : Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
[-56 -16]How it works: a += x writes the result back into a, so the result must fit a's dtype — a float result cannot be stored in an int array. (scores = scores + 0.5 works, because it creates a new float array.) Fixed-size integers can also overflow: 100 + 100 = 200 does not fit in int8, so it wraps to -56 without any error. NumPy's default int64 makes this rare, but it's good to know.
Python list vs NumPy
| Expression | Python list | NumPy array |
|---|---|---|
x + 10 | ❌ TypeError | ✅ adds 10 to every element |
x * 2 | repeats the list: [1, 2, 1, 2] | doubles every element: [2, 4] |
x + y | concatenates the lists | adds element by element |
x / y | ❌ TypeError | ✅ element-wise division |
| Speed on 1 million numbers | slow Python loop | fast C loop (often 10–100× faster) |
python
lst = [72, 45, 88]
arr = np.array(lst)
print("list * 2 :", lst * 2)
print("array * 2:", arr * 2)
print("list + list :", lst + lst)
print("array + array:", arr + arr)text
list * 2 : [72, 45, 88, 72, 45, 88]
array * 2: [144 90 176]
list + list : [72, 45, 88, 72, 45, 88]
array + array: [144 90 176]Common mistakes
- ❌ Expecting
a * bto be matrix multiplication. ✅*is element-wise; matrix product isa @ bornp.dot(a, b). - ❌ Adding arrays of different lengths (
(3,)+(2,)) →operands could not be broadcast together. ✅ Check shapes first. - ❌
int_arr += 0.5→UFuncTypeError. ✅int_arr = int_arr + 0.5or convert with.astype(float). - ❌ Writing a
forloop to add 10 to each element. ✅arr + 10. - ❌ Expecting
/on ints to give ints. ✅/always gives float; use//for integer division.
Interview tip
Q: What is vectorization and why is it fast?
A: Vectorization is writing operations on whole arrays (a + b) instead of Python loops. It is fast because the loop runs in compiled C over a contiguous block of same-typed memory — no per-element Python interpretation, type checks or object boxing.
Key points to remember
- Vectorized arithmetic applies + - * / // % ** to whole arrays without writing a loop.
- Operations are element-wise: result[i] depends only on the inputs at position i.
- With a scalar, the scalar is combined with every element (arr + 10).
- Two arrays must have the same shape (or broadcast-compatible shapes), otherwise ValueError: operands could not be broadcast together.
- / always returns float64; // is floor division; % is the remainder.
- a += x writes back into a, so the result must fit a's dtype (int += 0.5 fails).
- On lists, * repeats and + concatenates; on arrays they do maths.
Try it yourself
Scalar arithmetic on a whole array
Array with array: partnership and difference
Shapes must match
Practice: total score with bonus
Revision Flashcards
Tap a card to flip it and see the answer.
