Statistical functions

PERMUT

Matches all 3,436 recorded answers

Recorded: 3,432 in the answer bank and 4 workbook cells. How we measure this · See the Rust code

Local names in 40 languages
LanguageName in Excel
ArabicPERMUT
BulgarianPERMUT
CzechPERMUTACE
DanishPERMUT
GermanPERMUT
GreekPERMUT
English (Australia)PERMUT
English (United Kingdom)PERMUT
English (United States)PERMUT
SpanishPERMUTACIONES
EstonianPERMUT
FinnishPERMUTAATIO
FrenchPERMUTATION
HebrewPERMUT
CroatianPERMUT
HungarianVARIÁCIÓK
IndonesianPERMUT
ItalianPERMUT
JapanesePERMUT
KoreanPERMUT
LithuanianPERMUT
LatvianPERMUT
NorwegianPERMUT
DutchPERMUTATIES
PolishPERMUTACJE
Portuguese (Brazil)PERMUT
Portuguese (Portugal)PERMUTAR
RomanianPERMUT
RussianПЕРЕСТ
SlovakPERMUT
SlovenianPERMUT
Serbian (Latin)PERMUT
SwedishPERMUT
ThaiPERMUT
TurkishPERMÜTASYON işlevi
UkrainianPERMUT
VietnamesePERMUT
Chinese (Simplified)PERMUT
Chinese (Hong Kong)PERMUT
Chinese (Traditional)PERMUT

Names from Microsoft's support site.

What it does

PERMUT(number, number_chosen)

PERMUT(number, number_chosen) returns the number of ordered arrangements of number_chosen distinct objects drawn without replacement from number objects.

Writing n for number and k for number_chosen, this is the falling factorial:

P(n, k) = n! / (n - k)!
        = n · (n-1) · (n-2) · … · (n-k+1)        (k factors)

The two right-hand sides are the same integer and are not the same computation; the whole of the Numerical notes section below is about that difference.

Domain and range. After truncation to integers the documented domain is n ≥ 1, k ≥ 0, k ≤ n. On that domain P(n, k) is a positive integer, non-decreasing in n and, for fixed n, non-decreasing in k up to k = n. Boundary identities:

P(n, 0) = 1          the empty arrangement
P(n, 1) = n
P(n, n) = n!         = FACT(n)
P(n, n-1) = n!       the last factor is 1, so k = n-1 and k = n agree

The last of those is the cheapest self-consistency probe there is: two different calls that must return the same integer.

P(n, k) is exact in binary64 precisely while it is below 2^53. Beyond that the true value is an integer that a double cannot name, and every implementation is returning a rounded answer — which is why the order of the multiplications becomes observable.

Arguments

ArgumentMeaningDefault
numberThe size of the pool. Required.—
number_chosenHow many are arranged. Required.—

Microsoft describes both as integers and states that both arguments are truncated to integers, so PERMUT(5.9, 2.9) is the same call as PERMUT(5, 2). Truncation is toward zero, which matters only for negative inputs, and negative inputs are a documented #NUM! condition anyway.

Try it

Input cells (optional)

Example: {"B2": 3, "B3": 4}. A1 holds the formula. Other cells need values before a formula can read them.

Enter a formula, then calculate.

Runs locally in your browser with OneCalc. Its answer may differ from Excel. Use English function names and commas between arguments.

Quirks

Result and edge cases

Returns Number — an integer value where the integer is representable, and a rounded double where it is not.

  • Non-integer arguments are truncated before any validation, as documented.
  • k = 0 yields the empty arrangement, 1, for every admissible n.
  • k = n yields n! and therefore inherits the factorial's overflow wall: the largest representable factorial in binary64 is 170!, so PERMUT(n, n) cannot succeed for n ≥ 171. But PERMUT is not limited to n ≤ 170 in general — PERMUT(1000, 3) is a small number — and an implementation that computes n!/(n-k)! inherits a limit the function does not have. That is not hypothetical: it is one of the stagings the evidence record named below explicitly rules out.

Errors

As documented by Microsoft on the PERMUT page (retrieved for this page):

ErrorDocumented condition
#VALUE!number or number_chosen is nonnumeric
#NUM!number ≤ 0, or number_chosen < 0
#NUM!number < number_chosen

Error values arriving in either argument propagate under the ordinary coercion rules; see Coercion and lifting.

A documented boundary the earlier implementation does not honour

Microsoft's stated condition is number ≤ 0, not number < 0. Read literally, PERMUT(0, 0) is a #NUM! — even though the mathematics is unambiguous that there is exactly one arrangement of nothing chosen from nothing, and even though PERMUT(n, 0) = 1 holds for every other n.

The Handbook publishes this as a divergence rather than picking a side, because both readings are defensible and neither has been checked against Excel here:

  • Microsoft's inequality may be a documentation infelicity — n ≤ 0 written where n < 0 was meant — inherited from a COMBIN-style page where the same wording appears.

PERMUT(0, 0) is therefore the single highest-value probe on this page: one cell decides which of two published descriptions of Excel is wrong.

How to implement

Numerical notes

PERMUT looks like a function with no numerical content and is in fact a small case study in how staging changes answers.

The factorial-ratio staging is wrong twice over. Computing n! and (n-k)! and dividing loses in two independent ways. First, it manufactures an overflow the function does not have: n! is not representable for n ≥ 171, so a perfectly small PERMUT(200, 2) fails. Second, each factorial is itself a rounded double once past 2^53, and the quotient of two rounded values is not the rounded quotient — the two errors do not cancel. The evidence record attached to this page names exactly this staging as ruled out, reporting it as off by a recorded residual on the catalogue's own witness and as spuriously overflowing beyond n = 170.

The product staging is the right shape, and its details are still observable. Multiplying the k factors accumulates one rounding per multiply, so the answer depends on:

  1. Direction. Ascending (n-k+1 upward to n) and descending (n downward to n-k+1) are different sequences of roundings and give different last bits once the accumulator passes 2^53. Neither is universally better; the accurate-summation intuition (combine small terms first) does not transfer cleanly to products.
  2. Working precision. A product accumulated in 80-bit extended precision and rounded once per step to 64 bits is a third answer again, distinct from a pure-double accumulation and from a fully extended accumulation rounded once at the end. On x86 this is not an exotic choice — it is what a legacy x87 code path does by default.

What a careful independent implementation does. For results below 2^53 the honest answer is exact and any staging that avoids intermediate overflow will produce it; the correct strategy is to detect that regime and return the exact integer. Above it, the choice is between reproducing a target platform's staging (the excel-bitexact flavour's job) and computing the correctly rounded value (the math-correct flavour's job) — for which the standard route is exp(lgamma(n+1) - lgamma(n-k+1)) with a corrective term, or an extended-precision product with a final single rounding. Those two answers differ, and the Handbook's position is that both are right for their stated purpose. See About implementation options.

Rust code

Show the CalcFunc source of this function

Quoted from the public repository DnaCalc/DnaCalc, crates calc-func and calc-fml, at commit 9e1884369a67. Comments are the source's own. A kernel shared with other functions appears once, on its module page.

PERMUT · 3 lines · calc-func/src/catalogue/math.rs on GitHub
36 permut "PERMUT" (2, 2) [V "number", V "number_chosen"] |s, a, sv| {
    binary(s, a, k::permut_fn::permut_kernel)
}
permut_kernel · 23 lines · calc-func/src/ported/permut_fn.rs on GitHub
/// Worksheet `PERMUT` — bit-exact to 64-bit Excel on `x86_64` (W109 Phase 2,
/// unique surviving candidate over 402 live witnesses, build 20131): the
/// ASCENDING legacy x87 spill-loop product
/// `acc = RN53(RN64(acc · f))` for `f = n-k+1 ..= n` — not a factorial
/// ratio (the former `n!/(n-k)!` staging is 1 ULP off on the catalog witness
/// and overflows spuriously for large `n`).
pub fn permut_kernel(n: f64, k: f64) -> Result<f64, WorksheetErrorCode> {
    use crate::ported::excel_numeric::excel_x87_mul;
    let n = trunc_nonnegative(n)?;
    let k = trunc_nonnegative(k)?;
    if k > n {
        return Err(WorksheetErrorCode::Num);
    }
    let mut acc = 1.0f64;
    for f in (n - k + 1)..=n {
        acc = excel_x87_mul(acc, f as f64);
    }
    if acc.is_finite() {
        Ok(acc)
    } else {
        Err(WorksheetErrorCode::Num)
    }
}

Kernels shared with other functions

Argument and result plumbing

  • num catalogue/kit
  • out catalogue/kit

No implementation has been published with a Handbook test suite for this function.

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.

Excel 16.0 buildPlatform and CPUCaptured inputs
19929Windows, bitness not recorded, CPU not recorded140
20131Windows, bitness not recorded, AMD Ryzen 7 4800H with Radeon Graphics702
20430Windows, 64-bit, CPU not recorded2,730
  • XC-PERMUT-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.
  • XC-PERMUT-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.

Agreement on these compared inputs does not establish agreement on unmeasured inputs.

Recorded environments and comparison details.

Excel 16.0 build 19929

Windows, bitness not recorded, CPU not recorded

140 captured inputs are indexed for this environment. Capture dates are not recorded. This is a reading count, not a comparison with another build.

Excel 16.0 build 20131

Windows, bitness not recorded, AMD Ryzen 7 4800H with Radeon Graphics

702 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 16.0 build 20430

Windows, 64-bit, CPU not recorded

2,730 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.

Alternatives

Relationships

  • PERMUTATIONA is ordered selection with replacement: n^k rather than the falling factorial. Note the naming trap — the A suffix here does not mean what it means in AVERAGEA, COUNTA, MAXA and STDEVA, where it marks a variant that admits text and logicals. On PERMUTATIONA and COMBINA the suffix marks repetition allowed. Two unrelated conventions share one letter.
  • COMBIN is the unordered counterpart: COMBIN(n, k) = PERMUT(n, k) / FACT(k). That identity is exact in the integers and only approximately reproducible in floating point, which makes it a useful residual probe rather than a substitute computation.
  • COMBINA completes the two-by-two grid: ordered/unordered against with/without replacement. PERMUT (ordered, without), PERMUTATIONA (ordered, with), COMBIN (unordered, without), COMBINA (unordered, with).
  • FACT is the k = n diagonal, and FACTDOUBLE is unrelated despite the neighbouring name.
  • Confused with: COMBIN, constantly. If order matters — podium finishes, PINs, arrangements — it is PERMUT; if it does not — hands of cards, committees — it is COMBIN.

Named variants

No named variants are recorded yet.

Suggest a correction or contribute an implementation · For agents