{
  "category": "Statistical functions",
  "display_name": "PERCENTILE.INC",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.PERCENTILE.INC",
  "implementation_state": {
    "answer_bank": null,
    "detail": "Recorded: 5 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 5 recorded answers",
    "workbook_corpus": {
      "cells": 5,
      "matched": 5
    }
  },
  "implementations": [
    {
      "commit": "9e1884369a678158dd82d3d74188daf986995e87",
      "flavour": "excel-compatibility-candidate",
      "language": "Rust",
      "name": "CalcFunc",
      "own_code": [
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/statistics.rs#L303-L303"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/statistics::list",
        "catalogue/statistics::percentile",
        "ported/percentile_common::percentile_inc_kernel",
        "ported/percentile_common::percentile_exc_kernel",
        "ported/percentile_common::interpolate_sorted"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/statistics.rs#L303-L303",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 5 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.PERCENTILE.INC.json",
  "name": "PERCENTILE.INC",
  "notes": [],
  "schema": "efh.function-reference/v1",
  "section_order": [
    "what-it-does",
    "try-it",
    "quirks",
    "how-to-implement",
    "version-differences",
    "alternatives"
  ],
  "sections": {
    "alternatives": "\n### Relationships\n\n- **`PERCENTILE.EXC`** is the exclusive definition — Hyndman and Fan's\n  type 6 — with rank position `h = k(n+1)` instead of `1 + k(n−1)`, a restricted domain, and no\n  `k = 0` or `k = 1`. **The two functions return different numbers for the same data and the\n  same `k`**, and neither is wrong; they estimate the population quantile under different\n  plotting-position conventions. Choosing between them is a statistical decision, and the\n  Handbook's position is that a page which pretends otherwise is not being useful.\n- **`QUARTILE.INC`** is this function restricted to `k ∈ {0, 0.25, 0.5, 0.75, 1}`:\n  `QUARTILE.INC(array, q) = PERCENTILE.INC(array, q/4)`. A free consistency identity between two\n  Excel surfaces.\n- **`MEDIAN`** is `PERCENTILE.INC(array, 0.5)`, exactly, for every `n`.\n- **`MIN`** and **`MAX`** are the `k = 0` and `k = 1` endpoints.\n- **`PERCENTRANK.INC`** is the inverse direction — value in, fraction\n  out — and the two are *not* exact inverses of one another, because `PERCENTRANK.INC` truncates\n  its result to a fixed number of significant digits by default. That asymmetry is documented on\n  that page and is a real trap.\n- **`SMALL`** and **`LARGE`** return order statistics without interpolation:\n  `SMALL(array, i) = x₍ᵢ₎`. When the answer must be one of the observed values, these are the\n  functions.\n- **`TRIMMEAN`** and **`AGGREGATE`** are the neighbouring order-statistic consumers.\n\n\n",
    "how-to-implement": "\n### Numerical notes\n\n\nThe arithmetic here is a comparison sort and one linear interpolation, so there is no special\nfunction and no series — and the subtleties are correspondingly sharp rather than deep.\n\n**1. The interpolation form is not neutral.** Two algebraically identical expressions:\n\n    A:  x_j + g·(x_{j+1} − x_j)\n    B:  (1 − g)·x_j + g·x_{j+1}\n\nForm **A** is exact at `g = 0` and never leaves the interval, but loses precision when\n`x_{j+1} − x_j` cancels badly against large `x_j` — the classic case of two nearly equal large\nnumbers. Form **B** is exact at `g = 1` and is symmetric, but can produce a result **outside**\n`[x_j, x_{j+1}]` by an ULP when `g` is not exactly representable, which breaks monotonicity.\nThe safe construction is form A with a guard, or the `fma`-based\n`fma(g, x_{j+1} − x_j, x_j)`. This is not a hypothetical: quantile functions that are\nnon-monotone in `k` by one ULP are a real and reported class of bug.\n\n**2. `h = 1 + k(n−1)` is a rounding decision in disguise.** For `k` a \"nice\" decimal like\n`0.1`, `k(n−1)` is generally not an integer even when it mathematically should be — `0.1` is not\nrepresentable, so `0.1 × 10` need not be exactly `1`. The consequence is that a `k` intended to\nland exactly on a data point can instead produce `g = 1e−17`, giving an interpolated answer a\nfew ULP off the data value rather than the data value itself. **This is the single most likely\nsource of a \"wrong last digit\" complaint about this function**, and it is a property of decimal\ninput in binary arithmetic rather than of the algorithm. An implementation can mitigate it by\ncomputing `j` and `g` from an exactly-rounded product and snapping `g` to `0` or `1` within a\ntolerance — which is itself a decision to document, since it changes answers.\n\n**3. Selection, not sorting.** The answer needs only `x₍ⱼ₎` and `x₍ⱼ₊₁₎`, so a full sort is\n`O(n log n)` where `O(n)` selection (quickselect, introselect) suffices. For a single `k` on a\nlarge range that is the right algorithm; for many `k` on the same data, sorting once wins. This\nmatters in a spreadsheet where a column of percentiles over the same range is the common idiom.\n\n**4. Ties and stability are irrelevant here and matter next door.** Because the result depends\nonly on the *values* at positions `j` and `j+1`, no tie-breaking rule is needed and the sort\nneed not be stable. That is a genuine simplification relative to `MODE.SNGL` and `RANK.EQ`,\nwhere the tie rule is observable.\n\n**5. Comparison semantics.** Sorting requires a total order on the admitted values. If the\nadmitted set is all-numeric this is IEEE 754 ordering with the usual caveats about `−0.0`\n(compares equal to `0.0`, so either may be reported) and about whether a tolerant comparison is\nin play anywhere. Excel's tolerant-versus-exact comparison split is recorded upstream in\n`BUG-FUNC-004` for the lookup families; which side an order-statistic function falls on has not\nbeen established here.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns `Number`.\n\n- **`n = 1`.** The rank position is `h = 1 + k·0 = 1` for every `k`, so the single value is\n  returned for all admissible `k`. This is well defined here, and it is exactly the case where\n  the exclusive sibling has nothing to return — see\n  `PERCENTILE.EXC`.\n- **Repeated values** are handled by the ordering with no special case; the interpolation simply\n  has a zero-width gap.\n- **The result need not be a data value.** For most `k` it is a weighted average of two\n  observations, so `PERCENTILE.INC` of an integer data set is generally not an integer. Users\n  expecting \"one of my numbers\" want a different definition (`SMALL`, or the nearest-rank\n  convention, which Excel does not provide).\n- **Sorting cost.** The function is a selection problem, not a sort problem; see Numerical\n  notes.\n- **Arrays.** An aggregate over a grid, not a lift kernel; returns a scalar.\n\n\n\n### Errors\n\n\nAs documented by Microsoft on the `PERCENTILE.INC` page (retrieved for this page):\n\n| Error | Documented condition |\n|---|---|\n| `#NUM!` | `array` is empty |\n| `#VALUE!` | `k` is nonnumeric |\n| `#NUM!` | `k < 0` or `k > 1` |\n\nNote the boundary: `k = 0` and `k = 1` are **admissible**, which is precisely what distinguishes\nthis function from `PERCENTILE.EXC`. Note also that the documentation says nothing about an\narray containing no *numeric* values (as opposed to being empty), which under the ignore-rule is\na distinct situation, and nothing about error values inside the array.\n\nError values in either argument propagate under the ordinary coercion rules.\n\n\n",
    "sources": "- Microsoft, \"PERCENTILE.INC function\" —\n  <https://support.microsoft.com/en-us/office/percentile-inc-function-680f9539-45eb-410b-9a5e-c1355e5fe2ed>\n  (syntax; both required arguments; `k` in the range 0 to 1 inclusive; the `#NUM!` conditions\n  for an empty array and for `k < 0` or `k > 1`; the `#VALUE!` condition for a nonnumeric `k`;\n  and the remark that the function interpolates when `k` is not a multiple of `1/(n − 1)`, which\n  pins the definition). Retrieved for this page.\n- R. J. Hyndman and Y. Fan, \"Sample quantiles in statistical packages\", *The American\n  Statistician* 50 (1996) 361–365 — the taxonomy of nine sample-quantile definitions;\n  `PERCENTILE.INC` is their type 7.\n- Handbook, [Coercion and lifting](../model/02-coercion-and-lifting.md) and\n  [About implementation options](../model/07-implementation-options.md).\n- `data/functions/FUNC.PERCENTILE.INC.json` (arity 2, `Custom` kernel signature and coercion\n  profile, XLL symbol `xlfPercentile_inc`) and `data/functions/FUNC.PERCENTILE.json` (arity 2) —\n  the source of the unchanged-signature observation.\n\n\n",
    "version-differences": "No comparison between specific Excel builds is recorded here yet. This does not establish that all builds behave alike.",
    "what-it-does": "\n`PERCENTILE.INC(array, k)` returns the `k`-th sample quantile of the data, with `k` expressed\nas a fraction in `[0, 1]` and with linear interpolation between order statistics.\n\nLet `x₍₁₎ ≤ x₍₂₎ ≤ … ≤ x₍ₙ₎` be the admitted values sorted ascending. Define the **rank\nposition**\n\n    h = 1 + k·(n − 1)                    so   h ∈ [1, n]\n\nand split it as `h = j + g` with `j = ⌊h⌋` an integer and `g = h − j ∈ [0, 1)`. Then\n\n    PERCENTILE.INC(array, k) = x₍ⱼ₎ + g · ( x₍ⱼ₊₁₎ − x₍ⱼ₎ )\n\nwith the convention that `g = 0` returns `x₍ⱼ₎` outright, which covers `h = n` where `x₍ⱼ₊₁₎`\ndoes not exist.\n\nMicrosoft's page states the interpolation rule in terms of the same `n − 1`: \"If `k` is not a\nmultiple of `1/(n − 1)`, `PERCENTILE.INC` interpolates to determine the value at the `k`-th\npercentile.\" Those multiples are exactly the `k` values at which `h` lands on an integer, i.e.\n`k = (i−1)/(n−1)` for `i = 1 … n` — so **the `n` data points sit at equally spaced `k` values,\nwith the minimum at `k = 0` and the maximum at `k = 1`.**\n\n**This is Hyndman and Fan's type 7**, the \"inclusive\" definition, and it is the default in R,\nNumPy, Julia and most modern statistical software. Naming it matters: there are at least nine\ndefensible definitions of a sample quantile, they disagree on the same data, and every argument\nabout \"the wrong median\" or \"the wrong quartile\" between two systems reduces to which of the\nnine each one implements. Hyndman and Fan (1996) is the paper that catalogued them.\n\n**Domain and range.** `n ≥ 1` admitted values; `k ∈ [0, 1]` inclusive at both ends — the\ninclusive part of the name. The result lies in `[x₍₁₎, x₍ₙ₎]` and is a non-decreasing, piecewise\nlinear, continuous function of `k`. Special values:\n\n    k = 0     → x₍₁₎ = MIN(array)\n    k = 1     → x₍ₙ₎ = MAX(array)\n    k = 0.5   → MEDIAN(array)          for every n, odd or even\n    n = 1     → the single value, for every admissible k\n\nThe `k = 0.5` identity is exact and general: at `h = 1 + (n−1)/2 = (n+1)/2`, odd `n` lands on\nthe middle order statistic and even `n` lands exactly halfway between the two middle ones,\nwhich is Excel's `MEDIAN`. That makes `MEDIAN` a redundant special case of this function and a\nfree cross-check.\n\n**Why an interpolated quantile at all.** The empirical distribution function is a step\nfunction, so its inverse is not unique between order statistics; every sample-quantile\ndefinition is a rule for choosing a point in that gap. Type 7 chooses the linear interpolant of\nthe order statistics against the plotting positions `p_i = (i−1)/(n−1)`. It is the estimator\nthat makes the sample quantile function the piecewise-linear interpolant through the data\npoints themselves — which is why its endpoints are the observed minimum and maximum and why it\ncannot extrapolate beyond the observed range.\n\n\n\n### Arguments\n\n\nMicrosoft's page gives two required arguments:\n\n| Argument | Meaning | Required |\n|---|---|---|\n| `array` | \"The array or range of data that defines relative standing\" | yes |\n| `k` | \"The percentile value in the range 0 to 1, inclusive\" | yes |\n\n`k` is a fraction, not a percentage: the 90th percentile is `k = 0.9`, and `k = 90` is a\n`#NUM!`. This is the most common user error with this function and, mercifully, a loud one.\n\n"
  },
  "signature": {
    "display": "PERCENTILE.INC(array, k)",
    "parameters": [
      {
        "description": null,
        "name": "array",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "k",
        "optional": false,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 2,
        "min": 2
      },
      "category": "Statistical functions",
      "classification": {
        "arg_preparation_profile": "ValuesOnlyPreAdapter",
        "coercion_lift_profile": "Custom",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "None",
        "fec_dependency_profile": "None",
        "host_interaction_class": "None",
        "kernel_signature_class": "Custom",
        "rich_value_usage": "RichBlind",
        "surface_fec_dependency_profile": "RefOnly",
        "thread_safety_class": "SafePure",
        "volatility_class": "NonVolatile"
      },
      "descriptions": {
        "long": null,
        "short": "Value at a given percentile, with 0 and 1 included",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns the k-th percentile of values in a range",
        "microsoft_url": "https://support.microsoft.com/en-us/office/percentile-inc-function-680f9539-45eb-410b-9a5e-c1355e5fe2ed"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "bg-BG",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "cs-CZ",
          "name": "PERCENTIL.INC"
        },
        {
          "locale": "da-DK",
          "name": "FRAKTIL.MEDTAG"
        },
        {
          "locale": "de-DE",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "el-GR",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "en-AU",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "en-GB",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "en-US",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "es-ES",
          "name": "PERCENTIL.INC"
        },
        {
          "locale": "et-EE",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "fi-FI",
          "name": "PROSENTTIPISTE.SIS"
        },
        {
          "locale": "fr-FR",
          "name": "CENTILE.INCLURE*"
        },
        {
          "locale": "he-IL",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "hr-HR",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "hu-HU",
          "name": "PERCENTILIS.TARTALMAZ"
        },
        {
          "locale": "id-ID",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "it-IT",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "ja-JP",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "ko-KR",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "lt-LT",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "lv-LV",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "nb-NO",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "nl-NL",
          "name": "PERCENTIEL.INC"
        },
        {
          "locale": "pl-PL",
          "name": "PERCENTYL.PRZEDZ.ZAMK"
        },
        {
          "locale": "pt-BR",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "pt-PT",
          "name": "PERCENTIL.INC"
        },
        {
          "locale": "ro-RO",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "ru-RU",
          "name": "ПРОЦЕНТИЛЬ.ВКЛ"
        },
        {
          "locale": "sk-SK",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "sl-SI",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "sv-SE",
          "name": "PERCENTIL.INK"
        },
        {
          "locale": "th-TH",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "tr-TR",
          "name": "YÜZDEBİRLİK.DHL"
        },
        {
          "locale": "uk-UA",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "vi-VN",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "zh-CN",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "zh-HK",
          "name": "PERCENTILE.INC"
        },
        {
          "locale": "zh-TW",
          "name": "PERCENTILE.INC"
        }
      ],
      "signature": {
        "display": "PERCENTILE.INC(array, k)",
        "parameters": [
          {
            "description": null,
            "name": "array",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "k",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "PERCENTILE.INC",
      "version_marker": null,
      "xlcall": {
        "code": "502",
        "symbol": "xlfPercentile_inc"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/percentile-inc-function-680f9539-45eb-410b-9a5e-c1355e5fe2ed"
  },
  "try_it": {
    "formula": "=PERCENTILE.INC({1;2;3},1)"
  },
  "url": "https://handbook.dnacalc.com/functions/PERCENTILE.INC.html",
  "variants": [],
  "versions": []
}