{
  "category": "Statistical functions",
  "display_name": "NORM.S.INV",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.NORM.S.INV",
  "implementation_state": {
    "answer_bank": null,
    "detail": "Recorded: 3 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 3 recorded answers",
    "workbook_corpus": {
      "cells": 3,
      "matched": 3
    }
  },
  "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/distributions.rs#L75-L77"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "ported/excel_numeric::binary_with",
        "ported/excel_numeric::excel_x87_mul",
        "ported/excel_numeric/x87::mul",
        "ported/normal_dist_common::phi_kernel",
        "ported/normal_log_family::validate_probability_open_unit",
        "ported/normal_log_family::inverse_standard_normal_acklam_refined",
        "ported/normal_log_family::inverse_standard_normal",
        "ported/normal_log_family::norm_s_inv_kernel"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/distributions.rs#L75-L77",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 3 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.NORM.S.INV.json",
  "name": "NORM.S.INV",
  "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- **[NORM.S.DIST](FUNC.NORM.S.DIST.md)** is the forward function and, per Microsoft's text, the\n  thing this function searches over. The round trip is the natural test pair.\n- **[NORM.INV](FUNC.NORM.INV.md)** is the general case: `NORM.INV(p, μ, σ) = μ + σ·NORM.S.INV(p)`\n  mathematically. Whether Excel's two surfaces agree at `μ = 0, σ = 1` is unmeasured.\n- **`LOGNORM.INV`**, **`STANDARDIZE`** and **`Z.TEST`** are the other members of the normal\n  cluster.\n- **Confused with**: `NORM.S.DIST`, by readers who want \"the z-table\" and pick the wrong\n  direction — a z-table is read both ways and only one of these functions reads each way; and\n  with `NORM.S.INV(95)` where `NORM.S.INV(0.95)` was meant, which is a `#NUM!` rather than a\n  quiet wrong answer, mercifully.\n\n\n",
    "how-to-implement": "\n### Numerical notes\n\n\n**1. Conditioning first.** The amplification factor is `1/φ(z)`, which is `1` at the centre,\nabout `8` at `z = 2`, about `10⁴` at `z = 4`, and grows without bound. An error in the *input*\n`p` — including the rounding that put it into a double — is multiplied by that. A correctly\nrounded `NORM.S.INV` still returns an answer whose meaning is limited by the representation of\n`p`. Accuracy for this function is best stated as a round-trip property.\n\n**2. AS 241 is the reference algorithm.** Wichura's `PPND16` (*Applied Statistics* 37, 1988)\ndelivers about 16 significant digits across the whole representable domain using three rational\napproximations chosen by region:\n\n    |p − ½| ≤ 0.425                  central branch, in q = p − ½ and q²\n    otherwise, r = √(−ln min(p,1−p)) tail branches, split again at r ≈ 5\n\nThat reparameterization in `r` is the essential trick: it converts the square-root-of-a-log\nbehaviour into something a rational function can approximate uniformly. R's `qnorm`, Boost, and\nmost modern libraries descend from it. Weaker predecessors, worth naming because they are still\nin circulation: A&S 26.2.22 (about `3 × 10⁻³` absolute), A&S 26.2.23 (about `4.5 × 10⁻⁴`),\nBeasley–Springer AS 111 with Moro's tail patch, and Acklam's approximation. None of those is\nadequate as a reference; all of them are fine for a plot.\n\n**3. Newton and Halley refinement close the gap, and reconcile the two designs.** With the\nderivative available in closed form, a single Halley step from a good starting point reaches\nfull double precision:\n\n    u = (Φ(z) − p) / φ(z)\n    z ← z − u / (1 + z·u/2)\n\nAn implementation doing this *is* consuming the forward CDF, so its accuracy is derivative of\nthe CDF's — exactly what Microsoft's page says about `NORM.S.INV`. \"Iterative search\" and\n\"rational approximation plus refinement\" are not as far apart as the words suggest; what\nseparates them observationally is monotonicity and the forward-versus-reverse round-trip\nasymmetry described above.\n\n**4. The tails must be computed in the tail parameter, never by symmetry from a central\nformula.** Evaluating `Φ⁻¹(p)` for tiny `p` by reflecting a computation of `Φ⁻¹(1 − p)` throws\naway everything: `1 − p` rounds to `1` and the reflection returns `+∞` where a finite answer\nexists. This is the same complementary-probability trap that runs through the whole\ndistribution family, and it is why `p` and `1 − p` must be kept as separate inputs wherever a\nsurface can offer both.\n\n**5. The published assessment record.** McCullough and Wilson's series in *Computational\nStatistics & Data Analysis*, and Knüsel's assessments of Excel's distribution functions, report\non this lane across several Excel versions, with revisions around Excel 2003 and again when the\ndotted names arrived. Morten Welinder's Gnumeric work is the standard practical account of\nimplementing the normal quantile in a spreadsheet. Named as literature; no figure restated.\n\n\n",
    "quirks": "\n### The documented algorithm\n\n\nMicrosoft's page states, unusually explicitly, how the function is computed:\n\n> \"Given a value for probability, NORM.S.INV seeks that value z such that\n> NORM.S.DIST(z,TRUE) = probability. Thus, precision of NORM.S.INV depends on precision of\n> NORM.S.DIST. NORM.S.INV uses an iterative search technique.\"\n\nThat last sentence is the strongest algorithmic statement Microsoft makes anywhere in the\nnormal family. Three consequences follow from the *documentation* — the Handbook has not\nobserved Excel and does not assert that the description is current:\n\n1. **`NORM.S.INV` is documented as a root-finder over `NORM.S.DIST`**, not as a direct rational\n   approximation to `Φ⁻¹`. That is a different architecture from every standard statistical\n   library.\n2. **Its accuracy is documented as derivative of the forward CDF's**, and the conditioning\n   factor `1/φ(z)` then amplifies whatever error the CDF carries — most severely at exactly the\n   inputs where users care.\n3. **Round-trip in `p` should be near-perfect and monotonicity in `z` is not guaranteed.** A\n   search terminating on `|Φ(z) − p| < tol` reproduces `p` by construction while permitting\n   adjacent `p` values to map to the same or out-of-order `z`. A direct approximation behaves\n   the other way round. Testing both directions discriminates the two designs, which is the\n   highest-value experiment on this page.\n\n\n\n### Result and edge cases\n\n\nReturns `Number`.\n\n- **`p = 0.5`** returns `0` exactly.\n- **Logical arguments.** `TRUE` coerces to `1`, which is a documented `#NUM!` boundary, and\n  `FALSE` coerces to `0`, likewise. So both logicals are rejected by the domain rule rather\n  than by a type rule — an example of coercion succeeding and validation then failing.\n- **The two reachable extremes** described above, around `−38.5` and `+8.13`.\n- **Arrays.** The recorded profile is `Custom`; elementwise lifting is not settled here.\n\nEmpty, missing and error arguments follow the shared call model; see\n[Coercion and lifting](../model/02-coercion-and-lifting.md).\n\n\n\n### Errors\n\n\nAs documented by Microsoft on the `NORM.S.INV` page (retrieved for this page):\n\n| Error | Documented condition |\n|---|---|\n| `#VALUE!` | `probability` is nonnumeric |\n| `#NUM!` | `probability ≤ 0` or `probability ≥ 1` |\n\nA small documentation defect worth recording rather than silently correcting: **both error\nsentences on that page spell the function `NORMS.INV`** — a third spelling that names neither\nthe modern surface (`NORM.S.INV`) nor the legacy one (`NORMSINV`). No such function exists. It\nis a typographical error in the published page, and it is the kind of thing that sends a reader\nsearching for a function that was never shipped.\n\nError values in the argument propagate under the ordinary coercion rules.\n\n\n",
    "sources": "- Microsoft, \"NORM.S.INV function\" —\n  <https://support.microsoft.com/en-us/office/norm-s-inv-function-d6d556b4-ab7f-49cd-b526-5a20918452b1>\n  (syntax; the `probability` description; the `#VALUE!` and `#NUM!` conditions, both of which\n  the page spells `NORMS.INV`; and the statement that the function seeks the `z` at which\n  `NORM.S.DIST(z,TRUE)` equals the probability, that its precision depends on `NORM.S.DIST`'s,\n  and that it \"uses an iterative search technique\"). Retrieved for this page.\n- Handbook evidence record `EV-DIST-0018` — the ten-witness normal-group re-sweep; names\n  `NORM.S.INV` and `NORMSINV` as subjects and carries a reader warning against per-surface\n  attribution of its group figure.\n- M. J. Wichura, \"Algorithm AS 241: The percentage points of the normal distribution\",\n  *Applied Statistics* 37 (1988) 477–484 — `PPND16` and the `r = √(−ln min(p,1−p))`\n  reparameterization.\n- Abramowitz & Stegun, *Handbook of Mathematical Functions*, chapter 26 §26.2.22–26.2.23 (the\n  classical rational approximations) and §26.2.12 (the tail asymptotics behind the\n  `√(2 ln(1/p))` leading term).\n- J. D. Beasley and S. G. Springer, \"Algorithm AS 111\", *Applied Statistics* 26 (1977), with\n  Moro's tail modification — named for contrast.\n- B. D. McCullough and B. Wilson, *Computational Statistics & Data Analysis* (1999, 2002,\n  2005); L. Knüsel on Excel's distribution functions; M. Welinder's Gnumeric statistical work.\n  Named as literature; no figure restated.\n- Handbook, [Coercion and lifting](../model/02-coercion-and-lifting.md) and\n  [About implementation options](../model/07-implementation-options.md).\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`NORM.S.INV(probability)` returns the quantile of the **standard** normal distribution — mean\n`0`, standard deviation `1` — at probability `p`. It is the **probit** function:\n\n    NORM.S.INV(p) = Φ⁻¹(p) = z    where    Φ(z) = p\n                  = √2 · erf⁻¹(2p − 1)\n\n**Domain and range.** `p` must lie strictly inside `(0, 1)`; `p ≤ 0` and `p ≥ 1` are documented\n`#NUM!`. On that open interval `Φ⁻¹` is a strictly increasing, analytic bijection onto the whole\nreal line. No poles in the interior, no branch cuts; the singularities sit at the two endpoints,\nand they are essential in the practical sense — the function is unbounded there.\n\n**The endpoints are the whole story.** From the inverse-function rule,\n\n    d/dp Φ⁻¹(p) = 1 / φ(Φ⁻¹(p))\n\nand `φ` decays like `e^(−z²/2)`, so the derivative grows superpolynomially at both ends. The\nasymptotic form of the function itself is\n\n    Φ⁻¹(p) ~ −√( 2L − ln L − ln(2π) ),   L = ln(1/p),   as p → 0⁺\n\n— a square root of a logarithm, which is why the function is so flat in the middle and so steep\nat the edges, and why every good implementation reparameterizes the tails in\n`r = √(−ln min(p, 1−p))` rather than in `p`.\n\n**Identities and special values.**\n\n    Φ⁻¹(1/2) = 0                      exactly\n    Φ⁻¹(p) = −Φ⁻¹(1 − p)              reflection; exact\n    Φ(Φ⁻¹(p)) = p,   Φ⁻¹(Φ(z)) = z    round trips\n    Φ⁻¹(0.975) ≈ 1.959963984540054    the two-sided 95% constant\n\n`Φ⁻¹(1/2) = 0` is the only exactly nameable value, and it is this function's cheapest test.\nThe `0.975` quantile is worth listing because it is the number every confidence interval in\nevery textbook is built from, and because \"1.96\" is the rounding of it that people memorize.\n\n**The reachable range is asymmetric, and that is a binary64 fact.** The smallest positive\ndouble is about `4.9 × 10⁻³²⁴`, whose probit is about `−38.5`; the largest double strictly below\n`1` is `1 − 2⁻⁵³`, whose probit is about `+8.13`. So `NORM.S.INV` can reach far into the left\ntail and barely into the right one — not because the distribution is asymmetric (it is not) but\nbecause probabilities near `1` are stored with absolute spacing `2⁻⁵³` while probabilities near\n`0` keep relative precision into the subnormals. Anyone wanting a large positive quantile must\ncompute `−NORM.S.INV(q)` with `q` the small upper-tail probability.\n\n\n\n### Arguments\n\n\nMicrosoft's page gives one required argument:\n\n| Argument | Meaning | Required |\n|---|---|---|\n| `probability` | \"A probability corresponding to the normal distribution\" | yes |\n\nThe pinned catalogue supplies `NORM.S.INV(probability)` with one required argument.\n\n\n"
  },
  "signature": {
    "display": "NORM.S.INV(probability)",
    "parameters": [
      {
        "description": null,
        "name": "probability",
        "optional": false,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 1,
        "min": 1
      },
      "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": "The z at which the cumulative standard normal distribution reaches a given probability",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns the inverse of the standard normal cumulative distribution",
        "microsoft_url": "https://support.microsoft.com/en-us/office/norm-s-inv-function-d6d556b4-ab7f-49cd-b526-5a20918452b1"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "NORM.S.INV"
        },
        {
          "locale": "bg-BG",
          "name": "NORM.S.INV"
        },
        {
          "locale": "cs-CZ",
          "name": "NORM.S.INV"
        },
        {
          "locale": "da-DK",
          "name": "STANDARD.NORM.INV"
        },
        {
          "locale": "de-DE",
          "name": "NORM.S.INV"
        },
        {
          "locale": "el-GR",
          "name": "NORM.S.INV"
        },
        {
          "locale": "en-AU",
          "name": "NORM.S.INV"
        },
        {
          "locale": "en-GB",
          "name": "NORM.S.INV"
        },
        {
          "locale": "en-US",
          "name": "NORM.S.INV"
        },
        {
          "locale": "es-ES",
          "name": "INV.NORM.ESTAND"
        },
        {
          "locale": "et-EE",
          "name": "NORM.S.INV"
        },
        {
          "locale": "fi-FI",
          "name": "NORM_JAKAUMA.KÄÄNT"
        },
        {
          "locale": "fr-FR",
          "name": "LOI.NORMALE.STANDARD.INVERSE.N*"
        },
        {
          "locale": "he-IL",
          "name": "NORM.S.INV"
        },
        {
          "locale": "hr-HR",
          "name": "NORM.S.INV"
        },
        {
          "locale": "hu-HU",
          "name": "NORM.S.INVERZ"
        },
        {
          "locale": "id-ID",
          "name": "NORM.S.INV"
        },
        {
          "locale": "it-IT",
          "name": "NORM.S.INV"
        },
        {
          "locale": "ja-JP",
          "name": "NORM.S.INV"
        },
        {
          "locale": "ko-KR",
          "name": "NORM.S.INV"
        },
        {
          "locale": "lt-LT",
          "name": "NORM.S.INV"
        },
        {
          "locale": "lv-LV",
          "name": "NORM.S.INV"
        },
        {
          "locale": "nb-NO",
          "name": "NORM.S.INV"
        },
        {
          "locale": "nl-NL",
          "name": "NORM.S.INV"
        },
        {
          "locale": "pl-PL",
          "name": "ROZKŁ.NORMALNY.S.ODWR"
        },
        {
          "locale": "pt-BR",
          "name": "NORM.S.INV"
        },
        {
          "locale": "pt-PT",
          "name": "INV.S.NORM"
        },
        {
          "locale": "ro-RO",
          "name": "NORM.S.INV"
        },
        {
          "locale": "ru-RU",
          "name": "НОРМ.СТ.ОБР"
        },
        {
          "locale": "sk-SK",
          "name": "NORM.S.INV"
        },
        {
          "locale": "sl-SI",
          "name": "NORM.S.INV"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "NORM.S.INV"
        },
        {
          "locale": "sv-SE",
          "name": "NORM.S.INV"
        },
        {
          "locale": "th-TH",
          "name": "NORM.S.INV"
        },
        {
          "locale": "tr-TR",
          "name": "NORM.S.TERS"
        },
        {
          "locale": "uk-UA",
          "name": "NORM.S.INV"
        },
        {
          "locale": "vi-VN",
          "name": "NORM.S.INV"
        },
        {
          "locale": "zh-CN",
          "name": "NORM.S.INV"
        },
        {
          "locale": "zh-HK",
          "name": "NORM.S.INV"
        },
        {
          "locale": "zh-TW",
          "name": "NORM.S.INV"
        }
      ],
      "signature": {
        "display": "NORM.S.INV(probability)",
        "parameters": [
          {
            "description": null,
            "name": "probability",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "NORM.S.INV",
      "version_marker": null,
      "xlcall": {
        "code": "540",
        "symbol": "xlfNorm_s_inv"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/norm-s-inv-function-d6d556b4-ab7f-49cd-b526-5a20918452b1"
  },
  "try_it": {
    "formula": "=NORM.S.INV(0.975)"
  },
  "url": "https://handbook.dnacalc.com/functions/NORM.S.INV.html",
  "variants": [],
  "versions": []
}