Skip to content
induwara.lk
Premium
induwara.lkAI · Machine learning

NDCG Calculator (Normalized Discounted Cumulative Gain)

Paste a ranked list of relevance scores and get NDCG@k, plus the DCG, IDCG, ideal ordering and every position's gain and log discount. Linear or exponential gain, matches scikit-learn's ndcg_score. No signup, nothing uploaded.

By Induwara AshinsanaUpdated Sep 6, 2026
NDCG calculator

The graded relevance of each result, in the order your model ranked them. Separate with commas, spaces, or new lines. Non-negative numbers only.

Gain type

Score only the top k results (e.g. 10 for NDCG@10). Leave empty to use the whole list.

Examples
NDCG@6
0.9608
0 to 1 · higher is better
DCG@6
6.8611
Your ranking
IDCG@6
7.1410
Ideal ranking
Reading
Excellent ranking
NDCG@696.08% of ideal

Cross-check. The row-by-row form (each gᵢ divided by its log2 discount) gives 0.9608; the independent gain·discount vector form — how scikit-learn computes it — gives 0.9608. They reconcile, as they must.

Ideal ordering (used for IDCG)

[3, 3, 2, 2, 1, 0]

Per-position working (your ranking)

Rank irelᵢgain gᵢlog2(i+1)gᵢ / log2(i+1)
13.00003.00001.00003.0000
22.00002.00001.58501.2619
33.00003.00002.00001.5000
40.00000.00002.32190.0000
51.00001.00002.58500.3869
62.00002.00002.80740.7124
DCG@6 total6.8611
DCG@6 = 6.8611
IDCG@6 = 7.1410
NDCG@6 = 6.8611 / 7.1410 = 0.9608

Method: NDCG@k = DCG@k / IDCG@k, with DCG@k = Σ gᵢ / log2(i+1) and IDCG@k the same on relevances sorted descending — scikit-learn ndcg_score and Järvelin & Kekäläinen (2002). Nothing leaves this page.

How it works

NDCG (Normalized Discounted Cumulative Gain)measures how good a ranked list is, rewarding relevant results placed near the top. It is the headline quality metric for search ranking, recommender systems and learning-to-rank models. The definition here follows Järvelin & Kekäläinen (2002) and the implementation in scikit-learn's ndcg_score.

Positions are 1-indexed. For a predicted ranking with relevance scores rel₁ … relₙ and cutoff k, the score is built in four steps:

  1. Gain. Turn each relevance into a gain. Linear gain is gᵢ = relᵢ; exponential gain is gᵢ = 2^relᵢ − 1 (Burges et al., 2005), which rewards highly relevant hits more.
  2. Discount. Divide each gain by a position discount dᵢ = log2(i + 1), so rank 1 has discount log2(2) = 1 and lower ranks are penalised more.
  3. DCG@k. Add the discounted gains over the top k: DCG@k = Σᵢ₌₁..ₖ gᵢ / log2(i+1).
  4. Normalise. Compute IDCG@k — the DCG of the ideal ranking, the same relevances sorted from best to worst — then NDCG@k = DCG@k / IDCG@k, a value in [0, 1].

When IDCG@k is 0 — every relevance is 0 — NDCG is undefined because it would divide by zero. The tool reports 0 and flags it, the same convention scikit-learn uses. If you set k larger than the number of items, it is clamped to the list length with a notice. As a credibility check, the calculator computes NDCG a second way — the gain·discount vector form scikit-learn uses internally — and confirms the two routes agree to floating-point precision. This version scores one ranking and derives the ideal order by sorting the relevances you enter; mean NDCG across many queries is a separate calculation.

Choosing the cutoff k

The cutoff decides how much of the list you are willing to be judged on. Reporting NDCG over the full list flatters a system, because the log discount makes positions 50 to 100 contribute almost nothing while still inflating both DCG and IDCG. Web search teams normally quote NDCG@10 because that is roughly one results page; recommender feeds use @5 or @20; a RAG retriever is usually evaluated at the number of chunks actually pasted into the prompt — if you stuff 8 passages into context, NDCG@8 is the honest number. Pick one k, write it down, and keep it fixed across every model you compare. Changing k mid-experiment changes the scale of the metric, not just the score.

Binary vs graded relevance

NDCG was designed for graded relevance — TREC-style judgements on a 0–3 or 0–4 scale, where 3 means “perfect answer” and 1 means “marginally useful”. It works with binary 0/1 labels too, and many teams use it that way, but with only two grades the metric loses most of what makes it better than simpler alternatives; at that point Precision@K and Recall@K are easier to explain to non-specialists. The gain choice matters more as the scale widens: with grades 0–4, exponential gain makes a grade-4 document worth 15 while a grade-2 is worth 3, so a single misplaced top-grade result moves the score far more than it would under linear gain. Neither convention is “correct” — but a linear NDCG and an exponential NDCG are different metrics and must never be compared to each other.

What NDCG does not tell you

Three limitations are worth stating plainly. First, unjudged documents are treated as relevance 0. If your judgement pool was built from an older system's results, a genuinely good new result that nobody ever labelled is scored as useless, and the new model is penalised for finding it. Second, NDCG is normalised per query, so it cannot tell you whether a query had ten excellent answers or one mediocre one — a query with a single grade-1 document can still score 1.0 simply by ranking that document first. Third, the score says nothing about diversity, freshness or duplicate results: ten copies of the same relevant page score exactly as well as ten distinct ones. Read NDCG alongside a coverage metric such as mean Average Precision, not on its own.

NDCG vs DCG, MRR, MAP and Precision@K

Ranking metrics are easy to confuse because they all produce a number between 0 and 1 from a ranked list. What separates them is which piece of the list they look at and what kind of label they need.

  • DCG — the un-normalised sum of discounted gains. Useful as a debugging intermediate, useless as a reported figure, because its ceiling depends on how many relevant documents the query happens to have. Always divide by IDCG before comparing anything.
  • NDCG — DCG scaled to [0, 1] by the ideal ordering. Needs graded relevance to shine, scores every position in the top k, and is the default for web search, learning-to-rank and reranker evaluation.
  • MRR — the reciprocal of the rank of the first relevant hit, averaged across queries. It ignores everything below that first hit entirely, which makes it the right metric for one-correct-answer tasks and the wrong one for a feed. The Mean Reciprocal Rank calculator works from the same kind of relevance list this page accepts.
  • MAP — the mean of Average Precision, which averages precision at every rank where a relevant document appears. It uses binary labels and rewards finding all the relevant items, so it is stricter than NDCG about recall and blind to relevance grades.
  • Precision@K / Recall@K — plain counts inside the top k, with no position discount at all. Swapping ranks 1 and 5 does not change Precision@5, but it does change NDCG@5. They are the metrics to quote when a stakeholder needs a number they can reason about without a formula.

A practical pairing for retrieval work: report NDCG@10 as the headline, Recall@K to prove the retriever is not dropping relevant documents, and MRR when a single correct answer exists. If you are tuning a two-stage pipeline, evaluate the first-stage retriever and the reranker separately — a reranker that raises NDCG by 0.04 may not be worth its latency and per-query API cost, and you can only see that trade-off if the two stages are scored apart.

Reading your NDCG score

NDCG has no universal pass mark. A score of 0.62 can be excellent on a hard, ambiguous query set and poor on an easy one, so the absolute value is far less informative than the comparison. The bands below are the reading aid this calculator prints next to your result — treat them as rough orientation, not a grading scale.

  • 1.000 — perfect. Your ordering already equals the ideal ordering of the same relevances. On a short list this is common and not especially meaningful.
  • 0.90 – 0.999 — excellent. The top positions are almost all in the right order; remaining errors are usually deep in the list where the discount hides them.
  • 0.70 – 0.90 — good. Typically a correct top result with some shuffling below it, or one high-grade document ranked a few places too low.
  • 0.50 – 0.70 — fair. Relevant material is present but not concentrated at the top; this is where reranking usually pays for itself.
  • below 0.50 — poor. Check the labels before blaming the model: an off-by-one in how you paired predictions with judgements produces exactly this.

Two sanity checks are worth running before you trust any figure. Reverse your list — the worst possible ordering — and confirm the score drops sharply; if it barely moves, your relevances are probably all equal. Then re-score with the same list sorted descending, which must give exactly 1.000. The preset buttons above the calculator run both checks in one click. Finally, remember that a difference of 0.01 between two models on a few dozen queries is noise; report NDCG over a few hundred queries, or run a significance test before calling a win.

Worked examples

Full list, linear gain — rel = [3, 2, 3, 0, 1, 2], k = 6

  1. DCG = 3/1 + 2/log2(3) + 3/log2(4) + 0 + 1/log2(6) + 2/log2(7)
  2. = 3 + 1.2618595 + 1.5 + 0 + 0.3868528 + 0.7124143 = 6.8611266
  3. ideal order = [3, 3, 2, 2, 1, 0]
  4. IDCG = 3/1 + 3/log2(3) + 2/log2(4) + 2/log2(5) + 1/log2(6) + 0
  5. = 3 + 1.8927893 + 1 + 0.8613531 + 0.3868528 = 7.1409952
  6. NDCG = 6.8611266 / 7.1409952 = 0.9608

NDCG@3, exponential gain — rel = [2, 0, 1, 3, 2], k = 3

  1. gains (2^rel − 1) = [3, 0, 1, 7, 3]
  2. DCG@3 = 3/log2(2) + 0/log2(3) + 1/log2(4) = 3 + 0 + 0.5 = 3.5
  3. ideal gains (rel sorted [3,2,2,1,0]) = [7, 3, 3, 1, 0]; top-3 = [7, 3, 3]
  4. IDCG@3 = 7/1 + 3/log2(3) + 3/log2(4) = 7 + 1.8927893 + 1.5 = 10.3927893
  5. NDCG@3 = 3.5 / 10.3927893 = 0.3368

Comparing two models on the same query — linear gain, k = 4

  1. Model A ranked rel = [3, 1, 2, 0]; Model B ranked rel = [2, 3, 0, 1]
  2. DCG(A) = 3/1 + 1/log2(3) + 2/log2(4) + 0 = 3 + 0.6309298 + 1 = 4.6309298
  3. DCG(B) = 2/1 + 3/log2(3) + 0 + 1/log2(5) = 2 + 1.8927893 + 0.4306766 = 4.3234658
  4. same relevance multiset ⇒ one shared ideal [3, 2, 1, 0]
  5. IDCG = 3/1 + 2/log2(3) + 1/log2(4) + 0 = 3 + 1.2618595 + 0.5 = 4.7618595
  6. NDCG(A) = 4.6309298 / 4.7618595 = 0.9725
  7. NDCG(B) = 4.3234658 / 4.7618595 = 0.9079 ⇒ Model A wins

Edge case — all relevances 0, rel = [0, 0, 0]

  1. Every gain is 0, so DCG = 0 and IDCG = 0
  2. NDCG = 0 / 0 is undefined (division by zero)
  3. Reported as 0 with a note — the scikit-learn convention

Edge case — fractional relevance and k past the end, rel = [0.5, 1.5], k = 5

  1. k = 5 but only 2 items exist ⇒ k is clamped to 2 and the tool flags it
  2. DCG@2 = 0.5/1 + 1.5/log2(3) = 0.5 + 0.9463946 = 1.4463946
  3. ideal order = [1.5, 0.5]
  4. IDCG@2 = 1.5/1 + 0.5/log2(3) = 1.5 + 0.3154649 = 1.8154649
  5. NDCG@2 = 1.4463946 / 1.8154649 = 0.7967
  6. note: relevances need not be whole numbers — only non-negative

Frequently asked questions

Sources & references

Related tools

Rate this tool
Be the first to rate

Comments & feedback

Spotted a bug or want an improvement? Tell us — our team reviews every comment, and good ideas get built. Comments are public and anonymous.

Found a bug, edge case, or want to suggest an improvement?

Email me at [email protected] — most fixes ship within 24 hours.