Search results and recommendations have two properties worth scoring: the good items should be there, and they should be near the top. NDCG scores both at once.
It comes in three steps.
Discounted cumulative gain walks your ranking and adds up each item's relevance, divided by a penalty that grows the further down it sits:
Position i counts from 1, so the top item is divided by log2(2) = 1 — no penalty at all — the second by log2(3) ≈ 1.585, and so on.
Ideal DCG is the same sum computed on the best possible ranking: the same relevance scores sorted highest-first.
NDCG is DCG / IDCG, which pins the result into [0, 1] no matter how big the relevance numbers are.
Task: write ndcg(relevances, k) returning that ratio, rounded to 4 decimal places. relevances is already in the order your system served, and k is how many positions to score.
k entries count — for both DCG and the ideal. Sort the whole relevance list to find the ideal, then take its top k.0 (nothing relevant anywhere in the list), return 0.0 rather than dividing by zero.k may be larger than the list, in which case you score everything you have.The normalization is what makes this comparable across queries: one search with five great hits available and another with one can both still be scored out of 1.0.