{
  "category": "Statistical functions",
  "display_name": "T.TEST",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.T.TEST",
  "implementation_state": {
    "answer_bank": null,
    "detail": "Everything else matches (8 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 8 recorded answers differ in the last bits, worst 2 ULP",
    "workbook_corpus": {
      "cells": 8,
      "last_bit": 1,
      "matched": 7,
      "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#L342-L344"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/distributions::sample",
        "catalogue/distributions::whole",
        "catalogue/distributions::t_test_of",
        "ported/excel_numeric::binary_with",
        "ported/excel_numeric::excel_x87_add",
        "ported/excel_numeric::excel_x87_mul",
        "ported/excel_numeric::excel_x87_mul_add",
        "ported/excel_numeric/x87::mul",
        "ported/excel_numeric/x87::add",
        "ported/special_math_common::bratio_ftoi",
        "ported/special_math_common::bratio_spmpar1",
        "ported/special_math_common::bratio_exparg",
        "ported/special_math_common::bratio_esum",
        "ported/special_math_common::bratio_esum20",
        "ported/special_math_common::bratio_alnrel",
        "ported/special_math_common::bratio_rlog1",
        "ported/special_math_common::bratio_gam1",
        "ported/special_math_common::bratio_gamln1",
        "ported/special_math_common::bratio_gamln",
        "ported/special_math_common::bratio_algdiv",
        "ported/special_math_common::bratio_bcorr",
        "ported/special_math_common::bratio_gsumln",
        "ported/special_math_common::bratio_betaln",
        "ported/special_math_common::bratio_betaln_60",
        "ported/special_math_common::bratio_erf_nswc",
        "ported/special_math_common::bratio_erfc1",
        "ported/special_math_common::bratio_rexp",
        "ported/special_math_common::bratio_psi",
        "ported/special_math_common::bratio_fpser",
        "ported/special_math_common::bratio_apser",
        "ported/special_math_common::bratio_bpser",
        "ported/special_math_common::bratio_bup",
        "ported/special_math_common::bratio_brcomp",
        "ported/special_math_common::bratio_brcmp1",
        "ported/special_math_common::bratio_bfrac",
        "ported/special_math_common::bratio_bgrat",
        "ported/special_math_common::bratio_grat1",
        "ported/special_math_common::bratio_basym",
        "ported/special_math_common::bratio",
        "ported/statistical_tests_family::sample_mean",
        "ported/statistical_tests_family::sample_variance",
        "ported/statistical_tests_family::validate_positive_df",
        "ported/statistical_tests_family::t_probability",
        "ported/statistical_tests_family::t_test_paired_kernel",
        "ported/statistical_tests_family::t_test_equal_variance_kernel",
        "ported/statistical_tests_family::t_test_unequal_variance_kernel"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/distributions.rs#L342-L344",
      "state": "close",
      "suite": null,
      "summary": "Close: 1 of 8 recorded answers differ in the last bits, worst 2 ULP"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.T.TEST.json",
  "name": "T.TEST",
  "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- **`TTEST`** is the legacy compatibility spelling, documented to compute the same thing. The\n  Handbook's alias-pairing record for the legacy/modern statistical collapse does not list either\n  spelling among its subjects, so **nothing in the Handbook's record bears on whether `TTEST` and\n  `T.TEST` publish the same bits.** They are documented equivalents; that is a weaker statement\n  than it sounds.\n- **[T.DIST.RT](FUNC.T.DIST.RT.md)** and **[T.DIST.2T](FUNC.T.DIST.2T.md)** are the tail areas\n  this function's answer is, given the statistic and ν. A reader can reconstruct `T.TEST` from\n  them plus `AVERAGE`, `VAR.S` and `COUNT` — and doing so is the best available check on it.\n- **[T.INV.2T](FUNC.T.INV.2T.md)** is the inverse direction: `T.TEST` gives a `p`-value from\n  data, `T.INV.2T` gives a critical value from a `p`. Comparing a `T.TEST` result against a\n  chosen α is the same decision as comparing the statistic against `T.INV.2T(α, ν)`.\n- **`Z.TEST`** is the large-sample or known-σ counterpart, and it differs in shape as well as in\n  distribution: `Z.TEST` takes one sample and a hypothesized mean, and returns a **directional**\n  one-tailed probability, not a `|statistic|` tail area. See [Z.TEST](FUNC.Z.TEST.md) — the two\n  functions are not parallel and cannot be swapped by changing the distribution.\n- **`F.TEST`** tests the equality of variances, which is the assumption `type = 2` makes. Using\n  `F.TEST` to choose between `type = 2` and `type = 3` is a well-known statistical mistake (the\n  two-stage procedure has the wrong size); the modern advice is to use Welch unconditionally.\n- **Confused with**: the Data Analysis ToolPak's t-Test dialogs, which report the statistic, both\n  critical values and both `p`-values, and which are a different code path from this worksheet\n  function.\n\n\n",
    "how-to-implement": "\n### Numerical notes\n\n\nThree separable difficulties, and the third is the one that decides the answer.\n\n**The variances.** Every branch needs sample variances, and the classic hazard applies: computing\n`Σx² − (Σx)²/n` loses all significance when the mean is large relative to the spread. Two-pass or\nWelford accumulation is the fix, and the argument is Higham's §1.9 and Chan–Golub–LeVeque. This\nmatters more here than in `VAR.S` itself, because the variance feeds a ratio whose numerator is\n*also* a difference of nearly equal means — so the cancellation compounds. See\n`VAR.S` for the one-variable treatment.\n\n**The mean difference.** `x̄₁ − x̄₂` is a subtraction of nearly equal quantities under the null\nhypothesis — which is precisely the regime the test is designed for. When the two means agree to\nmost of their digits, the numerator of `t` is almost entirely rounding error. For a paired test\nthis is avoidable and important: differencing **first** (`dᵢ = x₁ᵢ − x₂ᵢ`, then average) is far\nmore accurate than averaging first and differencing after, because each `dᵢ` is a subtraction of\ntwo quantities that are genuinely close, while `x̄₁ − x̄₂` subtracts two quantities that have each\nalready accumulated rounding from `n` additions. Mathematically identical; numerically not.\n\n**The Welch degrees of freedom.** The Welch–Satterthwaite formula is a ratio of fourth powers of\nvariances, and it is delicate at the extremes: as one `sᵢ² → 0` the expression tends to\n`nᵢ − 1` in a way that is numerically awkward, and when both variances and sample sizes are equal\nit reduces exactly to `n₁ + n₂ − 2`. Implementations should form `u = s₁²/n₁` and `v = s₂²/n₂`\nonce and compute `(u+v)²/(u²/(n₁−1) + v²/(n₂−1))` from them, rather than expanding — the expanded\nform squares and cancels needlessly.\n\n**And then the tail.** Everything above feeds a t-distribution tail area, so the accuracy\ndiscussion of [T.DIST.RT](FUNC.T.DIST.RT.md#numerical-notes) applies unchanged: the tail must be\ncomputed as itself, not as one minus the CDF, or small `p`-values — the interesting ones — will be\ndestroyed.\n\nThe accuracy of Excel's hypothesis-test functions is part of the published literature on Excel's\nstatistical procedures; Morten Welinder's Gnumeric work and the assessments by Knüsel and by\nMcCullough & Wilson are the standing references. The Handbook names them and does not assert from\nthem what any current build does.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns `Number`, a probability in `(0, 1)`.\n\n- **The one-tail / two-tail relationship.** `tails = 2` is exactly twice `tails = 1`, since the\n  statistic's absolute value is used. Multiplication by two is exact in binary floating point, so\n  the two settings must agree exactly — a free self-consistency probe.\n- **A one-tailed `p`-value from `|t|` is not a directional test.** Because the statistic is taken\n  in absolute value, `T.TEST(a, b, 1, type)` and `T.TEST(b, a, 1, type)` return the same number.\n  A reader wanting a genuinely one-sided test with a direction must check the sign of\n  `AVERAGE(array1) − AVERAGE(array2)` themselves. The documentation does not warn about this, and\n  it is the most consequential silent trap in the function.\n- **`n = 1` in either group** leaves a variance undefined. For type 2 and 3 the statistic is not\n  computable; for type 1 with a single pair the difference has no sample standard deviation.\n  Undocumented.\n- **Zero variance in both groups** makes the denominator zero. If the means also coincide the\n  statistic is `0/0`. Undocumented.\n- **Unequal lengths** are documented as `#N/A` only for `type = 1`. For types 2 and 3 unequal\n  lengths are the normal case.\n- **Non-integer Welch degrees of freedom.** Type 3 produces a real ν, and the tail area must then\n  be evaluated at a non-integer ν. Whether Excel evaluates the t-distribution at the real ν, or\n  truncates it first, changes the answer — and truncating is the conservative-looking choice that\n  is actually wrong, because it discards the approximation's entire point. **Microsoft's page does\n  not say which happens.** Note the awkward fit with the neighbouring surfaces: `T.DIST.RT` and\n  `T.DIST.2T` document `deg_freedom` as an integer, and `T.INV`/`T.INV.2T` document truncation of\n  a non-integer — so if `T.TEST` type 3 calls those surfaces as documented, it cannot pass a real\n  ν through them. Either it does not use them, or the documentation is incomplete somewhere. This\n  is a documentation-versus-mathematics tension the Handbook records rather than resolves.\n\n\n\n### Errors\n\n\nAs documented on Microsoft's `T.TEST` page:\n\n| Error | Documented condition |\n|---|---|\n| `#N/A` | `array1` and `array2` have different numbers of data points and `type = 1`. |\n| `#VALUE!` | `tails` or `type` is nonnumeric. |\n| `#NUM!` | `tails` is any value other than 1 or 2. |\n\nNote what is missing. **The page states no condition for an out-of-range `type`.** `tails` gets an\nexplicit `#NUM!` rule; `type` gets none, even though the argument's documented value set is\nexactly `{1, 2, 3}`. Whether `type = 0` or `type = 4` produces `#NUM!`, some default test, or\nsomething else is undocumented, and this is a real gap rather than an oversight in this page's\nreading: the two arguments are described in the same table and treated asymmetrically in the\nremarks. Also undocumented: single-element groups, zero variance, and the treatment of the Welch\ndegrees of freedom.\n\nErrors in any argument propagate under the universal coercion rule. The Handbook has not verified\nany of this against Excel.\n\n\n",
    "sources": "\n- Microsoft, \"T.TEST function\" —\n  <https://support.microsoft.com/en-us/office/t-test-function-d4e08ec3-c545-485f-962e-276f7cbed055>\n  (syntax; the `tails` meaning; the `type` table 1 = paired, 2 = two-sample equal variance\n  (homoscedastic), 3 = two-sample unequal variance (heteroscedastic); `#N/A` for different\n  numbers of data points with `type = 1`; truncation of `tails` and `type` to integers; `#VALUE!`\n  for nonnumeric `tails` or `type`; `#NUM!` for `tails` other than 1 or 2; and the description of\n  the returned probability with the two-tailed value as double the one-tailed). Retrieved for\n  this page. The page states no condition for an out-of-range `type`.\n- B. L. Welch, \"The generalization of Student's problem when several different population\n  variances are involved\" (1947), and F. E. Satterthwaite (1946) — the origin of the type-3\n  degrees-of-freedom approximation.\n- M. Abramowitz and I. A. Stegun, *Handbook of Mathematical Functions*, section 26.7 (the\n  t-distribution whose tail this function returns).\n- N. J. Higham, *Accuracy and Stability of Numerical Algorithms*, §1.9, and T. F. Chan,\n  G. H. Golub and R. J. LeVeque on computing sample variances — the accumulation argument behind\n  the offset-invariance probe above.\n- M. Welinder's documentation of Gnumeric's statistical functions, and the Excel accuracy\n  assessments of R. Knüsel and of B. D. McCullough and B. Wilson — named as the standing\n  literature, not as evidence about any current build.\n- Handbook [Coercion and lifting](../model/02-coercion-and-lifting.md).\n- Handbook projections `data/functions/FUNC.T.TEST.json` (arity, `RefsVisibleInAdapter`),\n  `data/presence/FUNC.T.TEST.json` (the `statistical_tests_family` and `test_alias_family`\n  modules) and `data/battery/FUNC.T.TEST.json`.\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`T.TEST(array1, array2, tails, type)` returns the **probability associated with a Student's\nt-test** — the `p`-value for the null hypothesis that the two samples come from populations with\nequal means.\n\nIt is not one function. The `type` argument selects among three genuinely different tests, which\ndiffer in their statistic, in their degrees of freedom, and in what they assume:\n\n**Type 1 — paired.** The samples are matched observations; the test is a one-sample t-test on the\ndifferences `dᵢ = x₁ᵢ − x₂ᵢ`:\n\n    t = d̄ / (s_d / sqrt(n)),        ν = n − 1\n\nwhere `s_d` is the sample standard deviation of the differences. This requires equal lengths, and\nMicrosoft documents `#N/A` when they differ.\n\n**Type 2 — two-sample, equal variance (homoscedastic).** The two samples are independent and\nassumed to share a variance, which is estimated by pooling:\n\n    s_p² = ( (n₁−1)s₁² + (n₂−1)s₂² ) / (n₁ + n₂ − 2)\n\n    t = (x̄₁ − x̄₂) / ( s_p · sqrt(1/n₁ + 1/n₂) ),     ν = n₁ + n₂ − 2\n\n**Type 3 — two-sample, unequal variance (heteroscedastic).** Welch's test. The variances are not\npooled, and the degrees of freedom are approximated by the Welch–Satterthwaite formula:\n\n    t = (x̄₁ − x̄₂) / sqrt( s₁²/n₁ + s₂²/n₂ )\n\n    ν = ( s₁²/n₁ + s₂²/n₂ )² / ( (s₁²/n₁)²/(n₁−1) + (s₂²/n₂)²/(n₂−1) )\n\nThat ν is **not an integer**, and it is not intended to be one. It is a moment-matching\napproximation: the distribution of the Welch statistic is not exactly a t-distribution for any ν,\nand the formula chooses the ν whose t-distribution matches its first two moments. `ν` lies\nbetween `min(n₁, n₂) − 1` and `n₁ + n₂ − 2`.\n\nThe `p`-value is then a tail area of the t-distribution with those degrees of freedom:\n\n    tails = 1  →  p = P(T_ν > |t|)          =  T.DIST.RT(|t|, ν)\n    tails = 2  →  p = P(|T_ν| > |t|)        =  T.DIST.2T(|t|, ν)  =  2 · T.DIST.RT(|t|, ν)\n\nRange: `p ∈ (0, 1)`, approaching 1 as the sample means coincide and 0 as they separate.\n\nThe three types do not nest and do not agree. On the same data, type 2 and type 3 give different\n`p`-values whenever the sample variances differ, and type 1 gives a different answer again — often\na much smaller one, because pairing removes between-subject variation. Choosing the wrong `type`\nis not a rounding-level mistake; it is a different experiment.\n\n\n\n### Arguments\n\n\n| Argument | Meaning | Required |\n|---|---|---|\n| `array1` | \"The first data set.\" | Yes |\n| `array2` | \"The second data set.\" | Yes |\n| `tails` | 1 for the one-tailed distribution, 2 for the two-tailed. | Yes |\n| `type` | 1 = paired, 2 = two-sample equal variance, 3 = two-sample unequal variance. | Yes |\n\nMicrosoft documents that **`tails` and `type` are truncated to integers**. So `type = 2.9` is a\ntype-2 test, and `tails = 1.9` is one-tailed. That is worth knowing, because a `type` computed\nfrom a cell can silently land on a different test than intended.\n\n"
  },
  "signature": {
    "display": "T.TEST(array1, array2, tails, type)",
    "parameters": [
      {
        "description": null,
        "name": "array1",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "array2",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "tails",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "type",
        "optional": false,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 4,
        "min": 4
      },
      "category": "Statistical functions",
      "classification": {
        "arg_preparation_profile": "RefsVisibleInAdapter",
        "coercion_lift_profile": "Custom",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "None",
        "fec_dependency_profile": "RefOnly",
        "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": "Probability from Student's t-test that two samples have the same mean",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns the probability associated with a Student's t-test",
        "microsoft_url": "https://support.microsoft.com/en-us/office/t-test-function-d4e08ec3-c545-485f-962e-276f7cbed055"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "T.TEST"
        },
        {
          "locale": "bg-BG",
          "name": "T.TEST"
        },
        {
          "locale": "cs-CZ",
          "name": "T.TEST"
        },
        {
          "locale": "da-DK",
          "name": "T.TEST"
        },
        {
          "locale": "de-DE",
          "name": "T.TEST"
        },
        {
          "locale": "el-GR",
          "name": "T.TEST"
        },
        {
          "locale": "en-AU",
          "name": "T.TEST"
        },
        {
          "locale": "en-GB",
          "name": "T.TEST"
        },
        {
          "locale": "en-US",
          "name": "T.TEST"
        },
        {
          "locale": "es-ES",
          "name": "PRUEBA.T.N"
        },
        {
          "locale": "et-EE",
          "name": "T.TEST"
        },
        {
          "locale": "fi-FI",
          "name": "T.TESTI"
        },
        {
          "locale": "fr-FR",
          "name": "T.TEST*"
        },
        {
          "locale": "he-IL",
          "name": "T.TEST"
        },
        {
          "locale": "hr-HR",
          "name": "T.TEST"
        },
        {
          "locale": "hu-HU",
          "name": "T.PRÓB"
        },
        {
          "locale": "id-ID",
          "name": "T.TEST"
        },
        {
          "locale": "it-IT",
          "name": "T.TEST"
        },
        {
          "locale": "ja-JP",
          "name": "T.TEST"
        },
        {
          "locale": "ko-KR",
          "name": "T.TEST"
        },
        {
          "locale": "lt-LT",
          "name": "T.TEST"
        },
        {
          "locale": "lv-LV",
          "name": "T.TEST"
        },
        {
          "locale": "nb-NO",
          "name": "T.TEST"
        },
        {
          "locale": "nl-NL",
          "name": "T.TEST"
        },
        {
          "locale": "pl-PL",
          "name": "T.TEST"
        },
        {
          "locale": "pt-BR",
          "name": "T.TEST"
        },
        {
          "locale": "pt-PT",
          "name": "TESTE.T"
        },
        {
          "locale": "ro-RO",
          "name": "T.TEST"
        },
        {
          "locale": "ru-RU",
          "name": "СТЬЮДЕНТ.ТЕСТ"
        },
        {
          "locale": "sk-SK",
          "name": "T.TEST"
        },
        {
          "locale": "sl-SI",
          "name": "T.TEST"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "T.TEST"
        },
        {
          "locale": "sv-SE",
          "name": "T.TEST"
        },
        {
          "locale": "th-TH",
          "name": "T.TEST"
        },
        {
          "locale": "tr-TR",
          "name": "T.TEST"
        },
        {
          "locale": "uk-UA",
          "name": "T.TEST"
        },
        {
          "locale": "vi-VN",
          "name": "T.TEST"
        },
        {
          "locale": "zh-CN",
          "name": "T.TEST"
        },
        {
          "locale": "zh-HK",
          "name": "T.TEST"
        },
        {
          "locale": "zh-TW",
          "name": "T.TEST"
        }
      ],
      "signature": {
        "display": "T.TEST(array1, array2, tails, type)",
        "parameters": [
          {
            "description": null,
            "name": "array1",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "array2",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "tails",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "type",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "T.TEST",
      "version_marker": null,
      "xlcall": {
        "code": "541",
        "symbol": "xlfT_test"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/t-test-function-d4e08ec3-c545-485f-962e-276f7cbed055"
  },
  "try_it": {
    "formula": "=T.TEST({1;2;3;4},{2;3;5;6},2,2)"
  },
  "url": "https://handbook.dnacalc.com/functions/T.TEST.html",
  "variants": [],
  "versions": []
}