{
  "category": "Statistical functions",
  "display_name": "PHI",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.PHI",
  "implementation_state": {
    "answer_bank": {
      "excel_builds": [
        "20131",
        "20430",
        "?"
      ],
      "larger_numeric": 0,
      "last_bit": 0,
      "matched": 14406,
      "other_mismatch": 0,
      "refused": 0,
      "rows": 14406,
      "unread": 0,
      "worst_ulp": 0
    },
    "detail": "Recorded: 14,406 in the answer bank and 3 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 14,409 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#L110-L110"
      ],
      "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/phi_fn::phi_kernel"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/distributions.rs#L110-L110",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 14,409 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.PHI.json",
  "name": "PHI",
  "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\n- **`NORM.S.DIST(x, FALSE)`** computes the same mathematical function. `PHI` is the shorter\n  spelling of the non-cumulative standard normal, added later. Two surfaces for one density is\n  exactly the situation in which \"are they the same computation?\" must be asked rather than\n  assumed — and here the Handbook has an unusually pointed reason to ask: `EV-DIST-0022`\n  identifies `PHI`'s op-graph as a squaring, an exponential and a multiply by a *rounded*\n  `1/√(2π)`, with **no erf and no CDF anywhere in the chain**, while the normal CDF surfaces\n  necessarily have one. If Excel routed `PHI` through `NORM.S.DIST`, that identification would\n  look different. See [NORM.S.DIST](FUNC.NORM.S.DIST.md).\n- **`NORM.DIST(x, 0, 1, FALSE)`** and the legacy `NORMDIST(x, 0, 1, FALSE)` are two more\n  spellings of the same density. Four surfaces, one function, no published proof that any two\n  of them agree to the last bit.\n- **[GAUSS](FUNC.GAUSS.md)** is the neighbouring modern addition: `GAUSS(z) = Φ(z) − 0.5`, the\n  probability that a standard normal falls between `0` and `z`. `PHI` and `GAUSS` arrived\n  together and are constantly confused — `PHI` is the *density*, `GAUSS` is a *probability*.\n  They are related by `GAUSS'(z) = PHI(z)`. `EV-DIST-0018` names both, and records that both\n  were the ones that drifted in that sweep while the eight CDF-side witnesses did not; `GAUSS`\n  remained open there for want of an erf substrate, and `PHI` was identified later — by a route\n  that turned out not to be an erf substrate at all.\n- **`ERF`** and **`ERFC`** are the underlying special functions of the normal *integral*, not\n  of its density. `PHI` needs neither.\n- **`EXP`** is `PHI`'s engine. Any account of `PHI`'s last bits is mostly an account of `EXP`'s.\n- **Confused with**: `NORM.S.DIST(x)` written with the cumulative argument set to `TRUE`, which\n  is a completely different curve.\n\n\n",
    "how-to-implement": "\n### Numerical notes\n\n\n`PHI` is a two-operation function with one genuinely hard property, and it is a good miniature\nof why \"simple\" special functions are not.\n\n**1. The squaring is the accuracy bottleneck, not the exponential.**\n\nLet `x̂ = x(1 + δ)` be the stored argument and consider `e^(−x²/2)`. An absolute error `ε` in\nthe exponent produces a *relative* error of about `ε` in the result. Forming `x²` in double\nprecision introduces a relative error of up to `2^−53`, hence an absolute error in `x²/2` of\nabout `x²/2 · 2^−53`. So:\n\n    relative error of φ(x)  ≳  (x² / 2) · 2^−53\n\nAt `x = 10` that is about `5.5 × 10^−15` — tens of ULP. At `x = 30` it is about\n`5 × 10^−14` — hundreds of ULP. **The error grows quadratically in `x` and has nothing to do\nwith the quality of the exponential.** This is the single most important fact about\nimplementing a normal density, and it is why a `PHI` that is correctly rounded near the origin\ncan be far off in the tail while every individual operation is faithfully rounded.\n\nThe standard remedy is to carry `x²/2` in more than double precision: split `x` into a\nhigh and low part (Dekker–Veltkamp splitting, or a fused multiply-add if one is available),\nform `x²= x_hi² + 2x_hi·x_lo + x_lo²` as a double-double, and evaluate\n`e^(−h) · e^(−l)` with `l` small enough that `e^(−l) ≈ 1 − l` to full precision. Boost's normal\ndistribution and the better libm normal routines do a version of this; Cephes's `ndtr`\naddresses the same problem in the CDF by working through `erfc`.\n\n**2. The constant matters at the origin and only there.**\n\n`1/√(2π)` is irrational; every implementation multiplies by *some* double near it. Whether the\nimplementation stores the correctly rounded `1/√(2π)`, or computes `1/sqrt(2*pi)` at runtime\n(two roundings), or divides by a stored `√(2π)` (a different rounding again) is directly\nvisible at `x = 0`, where the exponential is exactly `1` and the answer is nothing but the\nconstant. This is why `PHI(0)` is a genuinely diagnostic single cell, and why the ruled-out\nlist on `EV-DIST-0022` includes \"PHI as a division by `RN(√(2π))`\" as a *distinct hypothesis\nfrom* the multiply — the two stagings differ in the last bit of the answer at the origin.\n\n**3. The subnormal band is a publication question, not an arithmetic one.**\n\nIn `37.6 ≲ |x| ≲ 38.6` the result is subnormal. What an implementation does there — compute\nfaithfully into the subnormal range, flush to zero, or flush at some particular threshold — is\na platform and code-path decision, not a mathematical one, and it is not derivable from the\nformula. `EV-DIST-0022` records that this had to be pinned against live observation.\n\n**4. What a careful independent implementation does.**\n\nFor the `natural-best` flavour: compute `x²/2` in double-double, exponentiate the high part\nwith a faithful `exp`, correct with the low part, and multiply by the correctly rounded\nconstant — giving a small stated bound over the whole real line including the subnormal band.\nFor the `math-correct` flavour: evaluate in higher precision and round once. For\n`excel-bitexact`: reproduce the identified op-graph including its rounding sequence and its\nflush behaviour. These are three different functions and each is right for its stated purpose;\nsee [About implementation options](../model/07-implementation-options.md).\n\nThe Handbook does not assert what Excel does internally beyond what the attached evidence\nrecords say, in their own scope.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns `Number`.\n\n- **Symmetry.** `PHI(x)` and `PHI(−x)` are mathematically equal. Whether they are equal in\n  their last bits depends on whether the implementation squares `x` before anything else —\n  a squaring is exactly symmetric, so a squaring-first staging gives exact symmetry for free.\n  That makes the symmetry test a *weak* probe of the op-graph and a *strong* probe of\n  correctness.\n- **Very small `|x|`.** Near the origin the function is flat (`φ'(0) = 0`), so `PHI` is\n  extremely well conditioned there; the relative error of the result is essentially the\n  relative error of the constant `1/√(2π)`.\n- **Arrays.** Elementwise, per the recorded lift profile.\n\n\n\n### Errors\n\n\nAs documented by Microsoft on the `PHI` page (retrieved for this page):\n\n| Error | Documented condition |\n|---|---|\n| `#NUM!` | `x` is a numeric value that is not valid |\n| `#VALUE!` | `x` uses a data type that is not valid, such as a nonnumeric value |\n\nThe `#NUM!` row is documented without a stated inequality — \"a numeric value that is not\nvalid\" names no boundary. Since `φ` is defined on the whole real line, it is not obvious what\ninput this row is meant to cover; the natural candidate is a magnitude so large that an\nintermediate `x²` overflows, but Microsoft's page does not say so and this Handbook will not\ninvent it. That gap is on the probe list.\n\nError values in the argument propagate under the ordinary coercion rules.\n\n\n",
    "sources": "- Microsoft, \"PHI function\" —\n  <https://support.microsoft.com/en-us/office/phi-function-23e49bc6-a8e8-402d-98d3-9ded87f6295c>\n  (syntax, the argument description, the `#NUM!` and `#VALUE!` conditions, and version\n  availability from Excel 2016). Retrieved for this page.\n- Handbook evidence record `EV-DIST-0018` — the ten-witness normal-group re-sweep, which names\n  `PHI` as a subject and whose group figure may not be attributed per surface.\n- Abramowitz & Stegun, *Handbook of Mathematical Functions*, chapter 26 §26.2 (`Z(x)`, the\n  normal density, and its Hermite-polynomial derivatives) and chapter 22 (Hermite polynomials).\n- Cephes (S. L. Moshier), `ndtr.c` — the normal integral and density in double precision;\n  cited as a reference implementation of the erfc-based route the identified Excel `PHI`\n  op-graph does *not* take.\n- T. J. Dekker, \"A floating-point technique for extending the available precision\",\n  *Numerische Mathematik* 18 (1971) — the splitting used to carry `x²/2` in double-double.\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.PHI.json` — arity 1, `NumToNum`,\n  `UnaryNumericScalarOrArrayElementwise` coercion profile, XLL symbol `xlfPhi`.\n- `data/presence/FUNC.PHI.json` — implementing module\n  `earlier-implementation/phi_fn.rs`, shared with no other surface.\n\n",
    "version-differences": "The recorded environments below distinguish a reading from a same-input comparison. Counts describe captured inputs in each environment; overlapping captures and comparisons are not totals of unique worksheet calls.\n\n| Excel 16.0 build | Platform and CPU | Captured inputs |\n|---|---|---:|\n| 19929 | Windows, bitness not recorded, CPU not recorded | 42 |\n| 20131 | Windows, bitness not recorded, AMD Ryzen 7 4800H with Radeon Graphics | 764 |\n| 20430 | Windows, 64-bit, CPU not recorded | 13,642 |\n\n- XC-PHI-001: build 19929 versus build 20131; 1 same-input pairs, 0 differing answers. Compared axes: excel-build. Numeric answers were compared by their recorded binary64 bits; other answers by typed value.\n- XC-PHI-002: build 19929 versus build 20430; 2 same-input pairs, 0 differing answers. Compared axes: excel-build. Numeric answers were compared by their recorded binary64 bits; other answers by typed value.\n- XC-PHI-003: build 20131 versus build 20430; 6 same-input pairs, 0 differing answers. Compared axes: excel-build. Numeric answers were compared by their recorded binary64 bits; other answers by typed value.\n\nAgreement on these compared inputs does not establish agreement on unmeasured inputs.\n\n[Recorded environments and comparison details](https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.PHI.json).",
    "what-it-does": "\n`PHI(x)` returns the value at `x` of the density function of the standard normal\ndistribution — Abramowitz & Stegun's `Z(x)`:\n\n    φ(x) = (1 / √(2π)) · e^(−x² / 2)\n\n**Domain and range.** Defined for every real `x`. The function is strictly positive,\neven (`φ(−x) = φ(x)`), and unimodal with its maximum at the origin:\n\n    φ(0) = 1 / √(2π)  ≈ 0.3989422804014327\n    φ(x) → 0          as |x| → ∞, faster than any exponential in |x|\n    range: (0, 1/√(2π)]\n\nThere are no poles and no branch cuts; `φ` is entire as a function of a complex argument. Its\ninflection points sit at `x = ±1`, which is where the standard deviation shows up in the\npicture of the curve.\n\n**Why this function exists at all.** It is the integrand of the normal probability integral,\nand the identities that matter are differential rather than algebraic:\n\n    φ'(x)  = −x · φ(x)\n    Φ'(x)  = φ(x)                       where Φ is the standard normal CDF\n    φ''(x) = (x² − 1) · φ(x)\n\nMore generally `φ^(n)(x) = (−1)^n He_n(x) φ(x)`, with `He_n` the probabilists' Hermite\npolynomials — A&S 26.2.36 and chapter 22. Every asymptotic expansion of the normal tail is\nbuilt by repeated integration by parts on `φ`, which is why a normal-tail routine that is\naccurate in the far tail almost always has an accurate `φ` inside it.\n\n**Special values.** `φ(0) = 1/√(2π)` is the one exactly-nameable value, and it is the reason a\nsingle cell is a meaningful test: any implementation that gets `φ(0)` wrong has a rounding\nerror in the constant, not in the exponential.\n\n\n\n### Arguments\n\n\n| Argument | Meaning | Default |\n|---|---|---|\n| `x` | The point at which the density is evaluated. Required. | — |\n\nMicrosoft describes `x` as \"the number for which you want the density of the standard normal\ndistribution\". There is no mean, no standard deviation, and no cumulative switch: `PHI` is the\nstandardized density and nothing else. To get a general normal density, scale it —\n`NORM.DIST(x, μ, σ, FALSE) = PHI((x − μ) / σ) / σ` mathematically, though whether the two\nExcel surfaces agree in their last bits is a separate, unchecked question.\n\n`PHI` is available from Excel 2016 onward per Microsoft's version list; it is a modern addition\nwith no legacy spelling.\n\n\n"
  },
  "signature": {
    "display": "PHI(x)",
    "parameters": [
      {
        "description": null,
        "name": "x",
        "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": "UnaryNumericScalarOrArrayElementwise",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "None",
        "fec_dependency_profile": "None",
        "host_interaction_class": "None",
        "kernel_signature_class": "NumToNum",
        "rich_value_usage": "RichBlind",
        "surface_fec_dependency_profile": "RefOnly",
        "thread_safety_class": "SafePure",
        "volatility_class": "NonVolatile"
      },
      "descriptions": {
        "long": null,
        "short": "Density of the standard normal distribution at z",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns the value of the density function for a standard normal distribution",
        "microsoft_url": "https://support.microsoft.com/en-us/office/phi-function-23e49bc6-a8e8-402d-98d3-9ded87f6295c"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "PHI"
        },
        {
          "locale": "bg-BG",
          "name": "PHI"
        },
        {
          "locale": "cs-CZ",
          "name": "PHI"
        },
        {
          "locale": "da-DK",
          "name": "PHI"
        },
        {
          "locale": "de-DE",
          "name": "PHI"
        },
        {
          "locale": "el-GR",
          "name": "PHI"
        },
        {
          "locale": "en-AU",
          "name": "PHI"
        },
        {
          "locale": "en-GB",
          "name": "PHI"
        },
        {
          "locale": "en-US",
          "name": "PHI"
        },
        {
          "locale": "es-ES",
          "name": "FI"
        },
        {
          "locale": "et-EE",
          "name": "PHI"
        },
        {
          "locale": "fi-FI",
          "name": "FII"
        },
        {
          "locale": "fr-FR",
          "name": "PHI*"
        },
        {
          "locale": "he-IL",
          "name": "PHI"
        },
        {
          "locale": "hr-HR",
          "name": "PHI"
        },
        {
          "locale": "hu-HU",
          "name": "PHI"
        },
        {
          "locale": "id-ID",
          "name": "PHI"
        },
        {
          "locale": "it-IT",
          "name": "PHI"
        },
        {
          "locale": "ja-JP",
          "name": "PHI"
        },
        {
          "locale": "ko-KR",
          "name": "PHI"
        },
        {
          "locale": "lt-LT",
          "name": "PHI"
        },
        {
          "locale": "lv-LV",
          "name": "PHI"
        },
        {
          "locale": "nb-NO",
          "name": "PHI"
        },
        {
          "locale": "nl-NL",
          "name": "PHI"
        },
        {
          "locale": "pl-PL",
          "name": "PHI"
        },
        {
          "locale": "pt-BR",
          "name": "PHI"
        },
        {
          "locale": "pt-PT",
          "name": "PHI"
        },
        {
          "locale": "ro-RO",
          "name": "PHI"
        },
        {
          "locale": "ru-RU",
          "name": "PHI"
        },
        {
          "locale": "sk-SK",
          "name": "PHI"
        },
        {
          "locale": "sl-SI",
          "name": "PHI"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "PHI"
        },
        {
          "locale": "sv-SE",
          "name": "PHI"
        },
        {
          "locale": "th-TH",
          "name": "PHI"
        },
        {
          "locale": "tr-TR",
          "name": "PHI"
        },
        {
          "locale": "uk-UA",
          "name": "PHI"
        },
        {
          "locale": "vi-VN",
          "name": "PHI"
        },
        {
          "locale": "zh-CN",
          "name": "PHI"
        },
        {
          "locale": "zh-HK",
          "name": "PHI"
        },
        {
          "locale": "zh-TW",
          "name": "PHI"
        }
      ],
      "signature": {
        "display": "PHI(x)",
        "parameters": [
          {
            "description": null,
            "name": "x",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "PHI",
      "version_marker": null,
      "xlcall": {
        "code": "578",
        "symbol": "xlfPhi"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/phi-function-23e49bc6-a8e8-402d-98d3-9ded87f6295c"
  },
  "try_it": {
    "formula": "=PHI(0)"
  },
  "url": "https://handbook.dnacalc.com/functions/PHI.html",
  "variants": [],
  "versions": [
    {
      "behaviour": "42 captured inputs are indexed for this environment. Capture dates are not recorded. This is a reading count, not a comparison with another build.",
      "excel_build": "16.0 build 19929",
      "platform": "Windows, bitness not recorded, CPU not recorded",
      "sources": [
        "https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.PHI.json"
      ]
    },
    {
      "behaviour": "764 captured inputs are indexed for this environment. Capture dates: 2026-07-11 to 2026-07-11. This is a reading count, not a comparison with another build.",
      "excel_build": "16.0 build 20131",
      "platform": "Windows, bitness not recorded, AMD Ryzen 7 4800H with Radeon Graphics",
      "sources": [
        "https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.PHI.json"
      ]
    },
    {
      "behaviour": "13,642 captured inputs are indexed for this environment. Capture dates: 2026-09-29 to 2026-09-29. This is a reading count, not a comparison with another build.",
      "excel_build": "16.0 build 20430",
      "platform": "Windows, 64-bit, CPU not recorded",
      "sources": [
        "https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.PHI.json"
      ]
    }
  ]
}