The formula
The numerator is the dot product. The denominator is the product of the two vectors' lengths.
The result is the cosine of the angle between them, which is bounded.
One means the same direction, zero means perpendicular, minus one means opposite.
What dividing by the norms buys
Without it you have the raw dot product, which grows with the length of either vector.
For text, length usually encodes something you do not want: a long document has a bigger vector than a short one on the same topic, purely because more words were counted.
Normalising throws that magnitude away and keeps only the direction, so a one-paragraph and a ten-page treatment of the same subject come out similar.
Its relationship to Euclidean distance
They are not independent. On vectors that have already been normalised to unit length, one determines the other.
So ranking by cosine similarity descending and by Euclidean distance ascending give the identical order, provided the vectors are unit length.
That is why embedding stores normalise on insert: it lets them use a plain dot product, which is a single fused instruction, and get cosine ordering for free.
One comparison, in order
- Compute the dot product of the two vectors.
- Compute each vector's Euclidean norm.
- Divide the dot product by the product of the norms.
- Guard against a zero norm, which is undefined rather than zero.
- Or normalise both vectors once, in advance, and take the dot product alone.
Where it is the wrong choice
If magnitude carries meaning, discarding it is a loss.
Count vectors where the total matters, and embeddings whose norm encodes confidence, are both cases where the plain dot product is the right metric.
It is also not a distance in the mathematical sense, because it does not satisfy the triangle inequality.
An index built on it therefore needs a metric conversion first.