Intuition What this page is
The parent note built the machinery: an embedding turns text into a vector, and cosine similarity measures how much two vectors point the same way. Here we stress-test that machinery against every case it can face — positive/negative/zero similarity, unequal lengths, orthogonal (unrelated) vectors, opposite vectors, degenerate zero vectors, and real retrieval word-problems. Nothing on this page needs symbols we haven't earned; each new symbol is re-anchored.
Before touching a single number, let us re-earn the three symbols we lean on the whole way down.
Definition The three symbols, re-anchored to a picture
a = ( a 1 , a 2 , … , a d ) — a vector , just an ordered list of d numbers. Picture it as an arrow from the origin to the point with those coordinates. (d = how many numbers = the number of axes.)
a ⋅ b = a 1 b 1 + a 2 b 2 + ⋯ + a d b d — the dot product . Multiply matched slots, add. See Dot Product .
∥ a ∥ = a 1 2 + a 2 2 + ⋯ + a d 2 — the norm (length of the arrow), from Pythagoras. See Vector Norms .
And the star of the show, Cosine Similarity :
sim ( a , b ) = ∥ a ∥ ∥ b ∥ a ⋅ b = cos θ
where θ is the angle between the two arrows . We use cosine — not raw dot product, not straight-line distance — because we want a number that answers exactly one question: "do these two arrows point the same way?" and ignores "how long are they?" . Length carries no meaning here (a long article about dogs and a one-line note about dogs mean the same thing).
Look at the figure: cos θ slides from + 1 (arrows on top of each other, angle 0° ), through 0 (arrows at a right angle, 90° ), down to − 1 (arrows pointing exactly opposite, 180° ). That single dial is what every example below reads off.
Every situation this topic throws at you is one of these cells. The examples that follow are tagged with the cell they cover, so by the end no scenario is left unseen .
#
Case class
What's special
sim value you expect
Example
A
Generic positive
ordinary partial overlap
0 < sim < 1
Ex 1
B
Same direction, different length
one is a scaled copy
sim = 1 exactly
Ex 2
C
Orthogonal
share no components
sim = 0
Ex 3
D
Opposite direction
one is a negative multiple
sim = − 1
Ex 4
E
Negative but not opposite
some slots disagree
− 1 < sim < 0
Ex 5
F
Degenerate zero vector
one vector is all zeros
undefined (÷0)
Ex 6
G
Pre-normalized inputs
already unit length
dot product is sim
Ex 7
H
Euclidean vs cosine agree
unit vectors, ranking
∥ a − b ∥ 2 = 2 − 2 cos θ
Ex 8
I
Real retrieval, top-k
word problem, pick winner
rank by sim
Ex 9
J
Exam twist: cross-model
different embedders
meaningless — trap
Ex 10
Intuition Why these ten cells cover
everything
Cosine similarity only ever produces a number in [ − 1 , 1 ] , or breaks (the zero vector). Cells A–E walk that entire range end-to-end; F is the one place it breaks; G–H are the practical shortcuts databases use; I–J are the real-world and exam faces of the same idea. There is no eleventh kind of case.
Worked example Ex 1 — Cell A: generic positive similarity
a = ( 1 , 2 , 2 ) , b = ( 2 , 0 , 1 ) .
Forecast: Guess before computing — do these look "somewhat related" or "totally unrelated"? Write down a number between 0 and 1.
Dot product: 1 ⋅ 2 + 2 ⋅ 0 + 2 ⋅ 1 = 2 + 0 + 2 = 4 .
Why this step? The dot product is the raw "agreement" — matched slots multiplied and summed. It is the numerator of cosine.
∥ a ∥ = 1 2 + 2 2 + 2 2 = 9 = 3 .
Why this step? We must divide out a 's length so only its direction survives.
∥ b ∥ = 2 2 + 0 2 + 1 2 = 5 .
Why this step? Same reason for b .
sim = 3 5 4 ≈ 0.596 .
Why this step? Divide agreement by both lengths → pure direction match.
Verify: 3 5 ≈ 6.708 , and 4/6.708 ≈ 0.596 ✓. Since 0.596 ∈ [ − 1 , 1 ] and is positive, the arrows lean the same way but not identically — angle arccos ( 0.596 ) ≈ 53.4° . Sanity: a right angle would give 0 , so being well below 90° matches "moderately similar."
Worked example Ex 2 — Cell B: same direction, different length ⇒ sim
= 1
a = ( 3 , 4 ) , b = ( 30 , 40 ) . Note b = 10 a .
Forecast: The raw dot product will be big (hundreds). Will the similarity be big too?
Dot: 3 ⋅ 30 + 4 ⋅ 40 = 90 + 160 = 250 .
Why this step? Numerator = agreement. Notice it's large — a tempting but misleading "similarity".
∥ a ∥ = 9 + 16 = 25 = 5 .
∥ b ∥ = 900 + 1600 = 2500 = 50 .
Why these steps? These lengths are exactly what inflated the dot product; we're about to cancel them.
sim = 5 ⋅ 50 250 = 250 250 = 1 .
Why this step? Dividing by the lengths strips the × 10 scaling. Same direction ⇒ angle 0° ⇒ cos 0° = 1 .
Verify: cos 0 = 1 ✓. This is the whole reason we divide by norms: raw dot said "250", but the meaning is identical ("100% same direction"). See Cosine Similarity .
Worked example Ex 3 — Cell C: orthogonal ⇒ sim
= 0
a = ( 1 , 0 ) , b = ( 0 , 1 ) .
Forecast: These arrows point along different axes. Similarity closer to 1, 0, or −1?
Dot: 1 ⋅ 0 + 0 ⋅ 1 = 0 .
Why this step? No slot is "on" in both vectors, so there is zero agreement.
∥ a ∥ = 1 , ∥ b ∥ = 1 .
sim = 1 ⋅ 1 0 = 0 .
Why this step? Numerator is 0, so no need to fear the denominator (both norms nonzero).
Verify: cos 90° = 0 ✓. A dot product of exactly zero always means a right angle — this is the geometric definition of orthogonal ("unrelated"). In retrieval this is a chunk that shares no meaning with the query.
Worked example Ex 4 — Cell D: opposite direction ⇒ sim
= − 1
a = ( 1 , 2 ) , b = ( − 2 , − 4 ) . Note b = − 2 a .
Forecast: Negative multiple. Where on the dial [ − 1 , 1 ] do we land?
Dot: 1 ⋅ ( − 2 ) + 2 ⋅ ( − 4 ) = − 2 − 8 = − 10 .
Why this step? Every matched slot disagrees in sign, so agreement goes fully negative.
∥ a ∥ = 1 + 4 = 5 , ∥ b ∥ = 4 + 16 = 20 = 2 5 .
sim = 5 ⋅ 2 5 − 10 = 2 ⋅ 5 − 10 = 10 − 10 = − 1 .
Why this step? 5 ⋅ 2 5 = 2 ⋅ ( 5 ) 2 = 10 ; the negative multiple gives the most-negative possible cosine.
Verify: cos 180° = − 1 ✓. This is the floor of the dial — arrows point exactly opposite. (In practice real embeddings rarely reach − 1 , but the math must handle it.)
Worked example Ex 5 — Cell E: negative but not opposite
a = ( 1 , 1 ) , b = ( 1 , − 2 ) .
Forecast: Some agreement (both have positive first slot), some disagreement (second slots clash). Net sign?
Dot: 1 ⋅ 1 + 1 ⋅ ( − 2 ) = 1 − 2 = − 1 .
Why this step? The disagreement in slot 2 outweighs the agreement in slot 1, so the numerator is negative but small.
∥ a ∥ = 1 + 1 = 2 , ∥ b ∥ = 1 + 4 = 5 .
sim = 2 5 − 1 = 10 − 1 ≈ − 0.316 .
Why this step? Small negative ⇒ angle just past 90° .
Verify: 10 ≈ 3.162 , − 1/3.162 ≈ − 0.316 ✓. Angle arccos ( − 0.316 ) ≈ 108.4° — obtuse, as expected for "leaning apart but not opposite." Fills the gap between Cell C (exactly 90° ) and Cell D (exactly 180° ).
Worked example Ex 6 — Cell F: the degenerate zero vector
a = ( 0 , 0 , 0 ) , b = ( 2 , 0 , 1 ) .
Forecast: A vector with no length and no direction. Can we even ask "which way does it point"?
Dot: 0 ⋅ 2 + 0 ⋅ 0 + 0 ⋅ 1 = 0 .
∥ a ∥ = 0 + 0 + 0 = 0 .
Why this step? This is the crux — the denominator will contain a factor of zero .
sim = 0 ⋅ 5 0 = 0 0 — undefined .
Why this step? Division by zero is not "0", it is undefined : the zero vector has no direction, so "angle between" is meaningless.
Verify: ∥ a ∥ = 0 , so the formula genuinely breaks ✓. What real systems do: they either reject empty/blank chunks before embedding, or add a tiny ε so norms are never exactly 0 . Never silently return 0 — that would falsely tag it "unrelated" instead of "invalid input."
0 0 as "orthogonal"
Feels right: "numerator is 0, so similarity 0." Truth: in Cell C the denominator was nonzero, giving a true 0 . In Cell F the denominator is also 0 , so the value is undefined , not "unrelated." Always guard against zero-length vectors.
Worked example Ex 7 — Cell G: pre-normalized vectors, dot product
is the similarity
Pre-normalize a = ( 3 , 4 ) : divide by its length 5 to get a ^ = ( 0.6 , 0.8 ) . Pre-normalize b = ( 0 , 5 ) to get b ^ = ( 0 , 1 ) . (The hat ^ means "unit length", i.e. norm exactly 1 .)
Forecast: If both arrows already have length 1, what shortcut appears?
Check lengths: ∥ a ^ ∥ = 0.36 + 0.64 = 1 = 1 ; ∥ b ^ ∥ = 0 + 1 = 1 .
Why this step? Confirm they really are unit vectors, so the denominator becomes 1 ⋅ 1 = 1 .
Dot: 0.6 ⋅ 0 + 0.8 ⋅ 1 = 0.8 .
Why this step? With denominator 1 , the dot product alone equals cosine similarity.
sim = 1 0.8 = 0.8 .
Verify: Directly on the originals, sim (( 3 , 4 ) , ( 0 , 5 )) = 5 ⋅ 5 20 = 0.8 ✓ — identical. Why databases do this: normalize once at insert time, then every query is a single cheap dot product (no square roots per comparison). This is the engineering point in the parent note.
Worked example Ex 8 — Cell H: Euclidean and cosine ranking agree for unit vectors
Using a ^ = ( 0.6 , 0.8 ) , b ^ = ( 0 , 1 ) from Ex 7.
Forecast: Straight-line distance and cosine feel different. For unit vectors, do they rank the same?
Squared Euclidean distance: ∥ a ^ − b ^ ∥ 2 = ( 0.6 − 0 ) 2 + ( 0.8 − 1 ) 2 = 0.36 + 0.04 = 0.40 .
Why this step? Euclidean distance is the ordinary ruler length between the two arrow-tips.
The identity for unit vectors: ∥ a ^ − b ^ ∥ 2 = 2 − 2 cos θ .
Why this step? Expand ( a ^ − b ^ ) ⋅ ( a ^ − b ^ ) = ∥ a ^ ∥ 2 + ∥ b ^ ∥ 2 − 2 ( a ^ ⋅ b ^ ) = 1 + 1 − 2 cos θ .
Plug cos θ = 0.8 : 2 − 2 ( 0.8 ) = 2 − 1.6 = 0.40 .
Why this step? Matches step 1 exactly — the two views agree.
Verify: 0.40 = 0.40 ✓. Because higher cos θ ⇒ smaller distance (monotone), sorting by cosine and sorting by Euclidean give the same top-k — but only after normalizing . That caveat is the whole point of the parent's Euclidean-vs-cosine mistake box.
Worked example Ex 9 — Cell I: real retrieval, pick the top-
k
Query q = embedding of "How do I reset my password?" . Candidate chunks with precomputed similarities:
C1 "Forgot password? Click 'Reset' on the login page." → sim = 0.81
C2 "Our office is open 9am–5pm." → sim = 0.12
C3 "Change your account password in Settings > Security." → sim = 0.74
Forecast: For top-k with k = 2 , which two chunks get sent to the LLM?
Sort descending: 0.81 ( C 1 ) > 0.74 ( C 3 ) > 0.12 ( C 2 ) .
Why this step? Higher cosine = smaller angle = closer meaning-direction; retrieval keeps the closest arrows.
Take the top k = 2 : { C 1 , C 3 } .
Why this step? These two share the "password reset" direction; C2 is nearly orthogonal (0.12 , angle ≈ 83° ).
Verify: max = 0.81 (C1), second = 0.74 (C3), and C 2 excluded since 0.12 < 0.74 ✓. These two chunks become the retrieved context handed to the model — the "R" in Retrieval-Augmented Generation . See also Chunking Strategies for why C1 and C3 are separate focused passages.
Worked example Ex 10 — Cell J: the exam trap, cross-model similarity
A student embeds the documents with model-X (space R 768 ) and the query with model-Y (space R 768 ). They compute cosine similarity and get 0.02 . They conclude "the document is irrelevant."
Forecast: Is 0.02 a trustworthy "irrelevant" verdict?
Both vectors are 768 -dimensional, so the dot product runs without error.
Why this step? The trap works precisely because nothing crashes — the shapes match.
But model-X and model-Y place meaning on different axes ; slot 5 might mean "animal" in X and "finance" in Y.
Why this step? Cosine only means something when both arrows live in the same coordinate space. Across models the axes don't correspond, so the angle is noise.
Correct action: re-embed the query with model-X (the same model as the documents) and recompute.
Verify: The number 0.02 is arithmetically valid but semantically meaningless — you cannot conclude anything. The parent's "same model for query and docs" rule is exactly this cell. (See Contrastive Learning for why each model's axes are self-consistent but model-specific.)
Reading the whole matrix back onto the cosine dial:
Cells A–E fill the dial from − 1 to + 1 ; F is the one place off the dial (undefined); G–J are the same dial read for engineering and exam contexts.
Recall Which cell is each?
sim exactly 1 , raw dot product large ::: Cell B — same direction, different length
sim exactly 0 with nonzero norms ::: Cell C — orthogonal / unrelated
formula gives 0/0 ::: Cell F — degenerate zero vector, undefined
two different embedding models compared ::: Cell J — meaningless, must re-embed with one model
unit vectors, distance ranks same as cosine ::: Cell H — ∥ a ^ − b ^ ∥ 2 = 2 − 2 cos θ
Mnemonic The full range in five words
"Opposite, obtuse, orthogonal, acute, identical" → sim marches − 1 → 0 → + 1 . Everything else is a special reading of that same march.