{
  "category": "Statistical functions",
  "display_name": "LOGNORM.INV",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.LOGNORM.INV",
  "implementation_state": {
    "answer_bank": null,
    "detail": "Everything else matches (5 workbook cells). Last-bit means a finite number within 16 ULP of Excel's.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "close",
    "state_label": "Close: last-bit deviations remain",
    "summary": "Close: 1 of 5 recorded answers differ in the last bits, worst 2 ULP",
    "workbook_corpus": {
      "cells": 5,
      "last_bit": 1,
      "matched": 4,
      "worst_ulp": 2
    }
  },
  "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#L89-L92"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/distributions::nums",
        "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_positive_sigma",
        "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::lognorm_inv_kernel"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/distributions.rs#L89-L92",
      "state": "close",
      "suite": null,
      "summary": "Close: 1 of 5 recorded answers differ in the last bits, worst 2 ULP"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.LOGNORM.INV.json",
  "name": "LOGNORM.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- **[LOGNORM.DIST](FUNC.LOGNORM.DIST.md)** — the forward distribution, and the exact inverse.\n  Note the argument-count asymmetry: the forward surface takes a `cumulative` flag and the\n  inverse does not, because only the CDF can be inverted. A density has no quantile.\n- **`LOGINV`** — the legacy spelling, retained in the Compatibility category\n  with the same three arguments. The documented relationship is that `LOGINV(p, μ, σ)` and\n  `LOGNORM.INV(p, μ, σ)` compute the same quantity. **Documented equivalence is not\n  demonstrated identity of computation.** The two are separate registered surfaces and may\n  reach the answer by different code; establishing that they return the same bits requires\n  evidence, and the Handbook has none for either surface. This is the cleanest\n  legacy/modern pair in the family to test, because the signatures are identical.\n- **[NORM.S.INV](FUNC.NORM.S.INV.md)** deserves separate mention as the accuracy bottleneck:\n  every digit `LOGNORM.INV` can deliver comes from the probit.\n- **[RAND](FUNC.RAND.md)** — `LOGNORM.INV(RAND(), μ, σ)` is the standard inverse-transform\n  lognormal sampler, and the reason the extreme-tail behaviour above is not academic: a\n  simulation with a million draws will visit `p` values within `10⁻⁶` of both endpoints.\n- **Confused with:** the mean and standard deviation of the data rather than of its logarithm;\n  and with `LOGNORM.DIST(..., FALSE)`, which is a density and not an inverse of anything.\n\n\n",
    "how-to-implement": "\n### Numerical notes\n\n\nThe mathematics is three operations. The accuracy question is entirely about the first.\n\n**The probit is the hard part.** `Φ⁻¹(p)` has no closed form. The implementations that matter,\nin increasing order of accuracy:\n\n- **Hastings' rational approximation**, published as Abramowitz and Stegun 26.2.22 and 26.2.23,\n  giving about `4.5·10⁻⁴` and `3·10⁻⁴` absolute error respectively. These are trivially cheap\n  and were embedded in an enormous amount of mid-century statistical software. Three or four\n  correct digits.\n- **Beasley and Springer (AS 111, 1977)** with Moro's tail refinement — about seven to nine\n  digits, and the version most often found in quantitative finance code.\n- **Wichura's AS 241 (1988)**, the `PPND16` routine: two rational approximations in `r =\n  √(−ln q)` covering the central and tail regions, delivering close to full double precision\n  across the representable range. This is the modern reference and what a careful\n  implementation uses.\n- **Newton or Halley refinement** of any of the above against a high-quality `Φ`, which\n  converges quadratically or cubically and can polish a nine-digit start to full precision in\n  one or two steps — at the cost of needing an accurate forward `Φ` and its derivative.\n\nThe published critique record on spreadsheet statistics is directly relevant here: Knüsel's\nassessments of statistical distribution accuracy, and McCullough and Wilson's *On the accuracy\nof statistical procedures in Microsoft Excel*, both singled out the inverse normal as a\nlow-accuracy routine in the Excel versions they examined, and tracked changes across releases.\nMorten Welinder's work on Gnumeric's statistical functions covers the same ground from the\nreimplementer's side. **The Handbook does not assert what any Excel build computes\ninternally**, and it has run none of those tests itself.\n\n**Error propagation through the exponential.** Let `δ` be the absolute error in `z_p`. Then\n\n    x̂ = exp(μ + σ(z_p + δ)) = x·exp(σδ)  ⇒  relative error ≈ σ·δ\n\nSo the **absolute** error of the probit becomes a **relative** error of the result, amplified\nby `σ`. A probit good to `3·10⁻⁴` — the Hastings level — gives a lognormal quantile good to\nabout `0.03%` when `σ = 1`, and to about `1.5%` when `σ = 50`. That is the entire argument for\nusing AS 241 rather than a cheap rational fit, stated quantitatively.\n\n**Where it is worst.** Both the probit's own difficulty and the amplification factor grow in\nthe tails: `z_p` is steep near the endpoints (`dz/dp = 1/φ(z)`, which blows up), and `σ|z_p|`\nis large exactly there. The far tail of `LOGNORM.INV` is therefore doubly disadvantaged, and it\nis also where simulation users spend their time.\n\n**What a careful implementation does.** Use AS 241 or an equivalently accurate probit; compute\n`μ + σ z_p` in one fused step if available, since the addition can cancel when `μ` and `σz_p`\nhave opposite signs and comparable size; and use a correctly rounded `exp` (fdlibm's\n`__ieee754_exp` and descendants). Do not compute the quantile by bisecting the forward CDF — a\ncommon shortcut that inherits the forward function's tail saturation and cannot reach the\nextremes at all.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns `Number`, always strictly positive when it returns at all.\n\n- **`σ ≤ 0`** → `#NUM!`.\n- **`p` extremely small** — the probit falls like `−√(2·ln(1/p))`, so `z_p` reaches about `−38`\n  at the smallest positive normal double and about `−39` at the smallest subnormal. The answer\n  is then `exp(μ − 38σ)`, which underflows to zero for quite ordinary `σ`. A returned zero is a\n  correct underflow, not an error, and it is indistinguishable from a value that genuinely\n  rounds to zero.\n- **`p` extremely close to 1** — the mirror case. Here the *representation of `p`* is the\n  binding limit, not the algorithm: the doubles just below 1 are spaced `2⁻⁵³` apart, so the\n  largest `p` distinguishable from 1 is `1 − 2⁻⁵³` and the largest reachable quantile is\n  `exp(μ + σ·Φ⁻¹(1 − 2⁻⁵³)) ≈ exp(μ + 8.13σ)`. Anything beyond that is unreachable through\n  this interface no matter how good the implementation is. This is the reason survival\n  analysis and reliability work want a complementary-probability entry point, and Excel does\n  not offer one for the lognormal.\n- **`σ` very large** — `exp(μ + σ z_p)` overflows to `#NUM!` for `|z_p|σ` above about 709. The\n  boundary is a legitimate parameter region, and where exactly it falls is unverified.\n- **Error values** in any argument propagate.\n\n\n\n### Errors\n\n\n| Error | Condition | Basis |\n|---|---|---|\n| `#NUM!` | `probability ≤ 0` or `probability ≥ 1`; or `standard_dev ≤ 0` | Documented by Microsoft on the `LOGNORM.INV` page |\n| `#NUM!` | Overflow of `exp(μ + σ z_p)` | Follows from the formula; the exact boundary is unverified |\n| `#VALUE!` | Any argument is non-numeric | Documented; also the shared coercion rule |\n| propagated | An error value in any argument | Shared coercion rule, chapter 02 |\n\n",
    "sources": "- Abramowitz and Stegun, *Handbook of Mathematical Functions*, chapter 26 — the normal\n  distribution, and 26.2.22/26.2.23 for the Hastings inverse approximations with their stated\n  error bounds.\n- Wichura, *Algorithm AS 241: The Percentage Points of the Normal Distribution*, Applied\n  Statistics 37 (1988) — the `PPND16` reference implementation of the probit.\n- Beasley and Springer, *Algorithm AS 111* (1977), with Moro's tail refinement — the\n  intermediate-accuracy route common in finance code.\n- Cody's `erf`/`erfc` work (Math. Comp. 1969; SPECFUN) and Boost.Math's normal-distribution\n  documentation — the forward function any Newton refinement would need.\n- fdlibm `__ieee754_exp` and its glibc/musl descendants; Muller, *Elementary Functions*.\n- Knüsel, and McCullough and Wilson, on statistical distribution accuracy in spreadsheets; and\n  Morten Welinder's work on Gnumeric's statistical functions. Named as published literature\n  about the family, not as evidence about this surface.\n- Handbook [LOGNORM.DIST](FUNC.LOGNORM.DIST.md) — the forward distribution and its evidence\n  records, none of which name this surface.\n- Handbook [Coercion and lifting](../model/02-coercion-and-lifting.md).\n- Handbook projections `data/functions/FUNC.LOGNORM.INV.json` (arity exactly 3,\n  `xlfLognorm_inv`) and `data/presence/FUNC.LOGNORM.INV.json` (module `normal_log_family.rs`,\n  shared with the whole `NORM`/`LOGNORM`/`CONFIDENCE` group).\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`LOGNORM.INV(probability, mean, standard_dev)` returns the **quantile** of the lognormal\ndistribution: the value `x` for which `P(X ≤ x) = p`.\n\nBecause the lognormal CDF is `F(x) = Φ((ln x − μ)/σ)`, inverting is a one-line exercise:\n\n    F(x) = p\n    ⇔  (ln x − μ)/σ = Φ⁻¹(p)\n    ⇔  x = exp( μ + σ·Φ⁻¹(p) )\n\nso\n\n    LOGNORM.INV(p, μ, σ) = exp( μ + σ·z_p ),   z_p = Φ⁻¹(p)\n\nwhere `Φ⁻¹` is the standard normal quantile function, universally called the **probit**. The\nfunction is therefore an exponential of an affine transform of the probit, and everything\ninteresting about it — its accuracy, its failure modes, its extreme-value behaviour — is\ninherited from `Φ⁻¹`.\n\n**Domain.** `0 < p < 1` strictly, `σ > 0`, `μ` any finite real. **Range:** `(0, ∞)`. The\nfunction is strictly increasing in `p`, with\n\n    p → 0⁺  ⇒  x → 0        p → 1⁻  ⇒  x → ∞\n    p = ½   ⇒  x = e^μ      (the median, independent of σ)\n\nThe last of those is worth remembering: at the median the probit is exactly zero, so the answer\nis `exp(μ)` regardless of `σ`. It is the cleanest single test case the function has.\n\n**The exact inverse relationship** with [LOGNORM.DIST](FUNC.LOGNORM.DIST.md) holds in\nmathematics:\n\n    LOGNORM.INV( LOGNORM.DIST(x, μ, σ, TRUE), μ, σ ) = x\n    LOGNORM.DIST( LOGNORM.INV(p, μ, σ), μ, σ, TRUE ) = p\n\nIn floating point neither round trip can be exact, and how much they lose is a measurable\nproperty of the pair. See Numerical notes.\n\n**Quantiles of a lognormal are multiplicative.** Since `x_p = e^μ · e^{σ z_p}`, the ratio of\ntwo quantiles depends only on `σ`: `x_{p₂}/x_{p₁} = exp(σ(z_{p₂} − z_{p₁}))`. That is the\nstructural reason the lognormal is the natural model for quantities that vary by percentages —\nincomes, particle sizes, failure times, asset prices under geometric Brownian motion, where\n`LOGNORM.INV` is precisely the inverse-transform sampler.\n\n\n\n### Arguments\n\n\n| Argument | Meaning | Admissible values |\n|---|---|---|\n| `probability` | `p`, the cumulative probability | `0 < p < 1`; required |\n| `mean` | `μ`, the mean of `ln X` | Any finite real; required |\n| `standard_dev` | `σ`, the standard deviation of `ln X` | `σ > 0`; required |\n\nAs on [LOGNORM.DIST](FUNC.LOGNORM.DIST.md), `mean` and `standard_dev` describe **`ln X`**, not\n`X`. Feeding this function the sample mean and sample standard deviation of untransformed data\nis the standard misuse and produces a plausible-looking wrong answer with no diagnostic.\n\nThe endpoints are genuinely excluded, not merely awkward. `p = 0` would require `Φ⁻¹(0) = −∞`\nand `p = 1` would require `+∞`; neither has a finite answer, so both are domain errors rather\nthan infinities.\n\n\n"
  },
  "signature": {
    "display": "LOGNORM.INV(probability, mean, standard_dev)",
    "parameters": [
      {
        "description": null,
        "name": "probability",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "mean",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "standard_dev",
        "optional": false,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 3,
        "min": 3
      },
      "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 value at which the cumulative lognormal distribution reaches a given probability",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns the inverse of the lognormal cumulative distribution",
        "microsoft_url": "https://support.microsoft.com/en-us/office/lognorm-inv-function-fe79751a-f1f2-4af8-a0a1-e151b2d4f600"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "bg-BG",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "cs-CZ",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "da-DK",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "de-DE",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "el-GR",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "en-AU",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "en-GB",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "en-US",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "es-ES",
          "name": "INV.LOGNORM"
        },
        {
          "locale": "et-EE",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "fi-FI",
          "name": "LOGNORM.KÄÄNT"
        },
        {
          "locale": "fr-FR",
          "name": "LOI.LOGNORMALE.INVERSE.N*"
        },
        {
          "locale": "he-IL",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "hr-HR",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "hu-HU",
          "name": "LOGNORM.INVERZ"
        },
        {
          "locale": "id-ID",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "it-IT",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "ja-JP",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "ko-KR",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "lt-LT",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "lv-LV",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "nb-NO",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "nl-NL",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "pl-PL",
          "name": "ROZKŁ.LOG.ODWR"
        },
        {
          "locale": "pt-BR",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "pt-PT",
          "name": "INV.NORMALLOG"
        },
        {
          "locale": "ro-RO",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "ru-RU",
          "name": "ЛОГНОРМ.ОБР"
        },
        {
          "locale": "sk-SK",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "sl-SI",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "sv-SE",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "th-TH",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "tr-TR",
          "name": "LOGNORM.TERS"
        },
        {
          "locale": "uk-UA",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "vi-VN",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "zh-CN",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "zh-HK",
          "name": "LOGNORM.INV"
        },
        {
          "locale": "zh-TW",
          "name": "LOGNORM.INV"
        }
      ],
      "signature": {
        "display": "LOGNORM.INV(probability, mean, standard_dev)",
        "parameters": [
          {
            "description": null,
            "name": "probability",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "mean",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "standard_dev",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "LOGNORM.INV",
      "version_marker": null,
      "xlcall": {
        "code": "537",
        "symbol": "xlfLognorm_inv"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/lognorm-inv-function-fe79751a-f1f2-4af8-a0a1-e151b2d4f600"
  },
  "try_it": {
    "formula": "=LOGNORM.INV(0.5,0,1)"
  },
  "url": "https://handbook.dnacalc.com/functions/LOGNORM.INV.html",
  "variants": [],
  "versions": []
}