{
  "category": "Math and trigonometry functions",
  "display_name": "BASE",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.BASE",
  "implementation_state": {
    "answer_bank": {
      "excel_builds": [
        "20430"
      ],
      "larger_numeric": 0,
      "last_bit": 0,
      "matched": 3560,
      "other_mismatch": 0,
      "refused": 0,
      "rows": 3560,
      "unread": 0,
      "worst_ulp": 0
    },
    "detail": "Recorded: 3,560 in the answer bank and 5 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 3,565 recorded answers",
    "workbook_corpus": {
      "cells": 5,
      "matched": 5
    }
  },
  "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/math.rs#L182-L187"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "ported/base_fn::int_to_base",
        "ported/base_fn::base_kernel"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/math.rs#L182-L187",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 3,565 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.BASE.json",
  "name": "BASE",
  "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- **`DECIMAL`** — the inverse. `DECIMAL(BASE(n, b), b)` should recover `n` for every admissible `n`\n  and `b`, and that round trip is the best oracle-free test for the pair. `DECIMAL(text, radix)`\n  reads what `BASE` writes.\n- **`DEC2BIN`, `DEC2HEX`, `DEC2OCT`** — the fixed-radix conversions, and they are **not** special\n  cases of `BASE`. Three differences matter:\n  1. They accept **negative** numbers and encode them in **two's complement** over a fixed width;\n     `BASE` has no sign convention at all.\n  2. They have **narrow ranges** (a small number of places) where `BASE` runs to the\n     exactly-representable-integer limit.\n  3. They take a `places` argument that behaves like `min_length` but is bounded.\n  A formula that swaps `DEC2HEX` for `BASE(x, 16)` changes behaviour on every negative input and on\n  every large one.\n- **`BIN2DEC`, `HEX2DEC`, `OCT2DEC`** — the fixed-radix readers, `DECIMAL`'s specialised cousins,\n  with the same two's-complement asymmetry.\n- **`BITAND` and the bit-operation family** — the other place the `2^48`-and-beyond integer limits\n  of Excel's numeric model surface.\n- **`ROMAN` / `ARABIC`** — the non-positional pair, and the useful contrast: `BASE` and `DECIMAL`\n  are a clean bijection on their domain because positional representation is unique, whereas\n  `ROMAN` and `ARABIC` are not, because Roman notation is not.\n- **`TEXT`** — the general formatter, which cannot do radix conversion.\n- **Confused with**: `DEC2HEX`, constantly, and with the idea that `BASE` returns a number.\n\n\n",
    "how-to-implement": "\n### Numerical notes\n\n\n`BASE` has no rounding error — every digit it produces is exact — but it sits on top of a\nfloating-point argument, and that is where all of its numerical content lives.\n\n**The `2^53` boundary.** `number` arrives as a binary64 double. Doubles represent every integer up\nto `2^53` exactly; above that, only even integers, then only multiples of 4, and so on. So for\narguments above `2^53` the *value the function receives is not the integer the user wrote*, and any\nrepresentation it produces is the correct representation of a different number. There is no way for\nthe function to detect this — the information is gone before the call. That is why `2^53` is the\nnatural upper bound for a radix formatter over doubles, and why an implementation that quietly\naccepts larger arguments is producing digits that look authoritative and are not.\n\nThis is the same boundary that limits exact integer arithmetic everywhere in the worksheet, made\nunusually visible because `BASE`'s whole output is digits.\n\n**The digit-count trap.** The tempting way to size the output buffer, or to compute a digit, is\n`floor(log(n) / log(b)) + 1`. This is wrong at and near exact powers of the radix: `LOG10(1000)`\ncomputed in floating point can land just below `3`, and the formula then reports three digits where\nfour are needed. Every careful implementation either computes the digit count by the repeated\ndivision itself, or computes it by logarithm and then *verifies* against a power. Knuth's treatment\nof radix conversion in *TAOCP* volume 2 section 4.4 is the standard reference; the general lesson\nis that a logarithm should never be the sole source of an integer count.\n\n**Repeated division versus repeated multiplication.** Extracting digits least-significant-first by\n`n mod b` then `n = floor(n/b)` is exact in integer arithmetic and, because every intermediate stays\nbelow the starting value, exact in doubles too as long as the start is below `2^53`. Extracting\nmost-significant-first by dividing by `b^k` requires forming `b^k`, which is exactly representable\nonly for small `k` in most radices, and is therefore the worse algorithm on a floating-point\nsubstrate.\n\n**Padding is not formatting.** `min_length` pads with the *digit* zero, which is a semantically\nmeaningful character in a positional system, not a cosmetic space. Padding a base-16 value to eight\nplaces produces a string that reads correctly as a base-16 numeral; the `TEXT` function's padding\nwould not.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns `Text`.\n\n- **Zero** is representable and its representation is the single digit `0` in every radix.\n- **Negative `number`.** There is no sign convention in the mathematics above, and the reference\n  engine's battery rejects negative inputs. This is the single biggest behavioural difference from\n  the fixed-radix conversion family — see *Relationships*.\n- **Radix 0 and radix 1** are rejected: no positional system exists for either.\n- **Radix above 36** exceeds the digit alphabet.\n- **Very large `number`.** The hard limit is `2^53`, and the reason is the argument type rather\n  than the algorithm — see the numerical notes.\n- **`min_length` larger than the representation** pads; smaller has no effect; zero or omitted\n  means no padding.\n- **Arrays.** All argument positions broadcast. The evidence record attached to this page concerns\n  exactly that: `BASE` is a named subject of an array-lift tranche, with its own witness row about\n  a `radix` argument supplied as an array producing a text-valued array result.\n\n\n### Errors\n\nThe condition column is deliberately imprecise about the exact bounds, because the exact bounds are\nundocumented in every source the Handbook retrieved. Sharpening it is what the probe list is for.\n\n\n",
    "sources": "- Microsoft Learn, \"WorksheetFunction.Base method (Excel)\" —\n  <https://learn.microsoft.com/en-us/office/vba/api/excel.worksheetfunction.base> (retrieved: the\n  description, the three parameters with `Arg3` optional, the `String` return type, and the\n  statement that leading zeros are not added when `min_length` is omitted; **no constraint on\n  `number` or `radix` and no error condition are stated there**).\n- Knuth, *The Art of Computer Programming*, volume 2, sections 4.1 and 4.4 — positional number\n  systems, the uniqueness theorem, and radix-conversion algorithms including the digit-count\n  pitfall.\n- IEEE Std 754-2019 — the binary64 significand width, hence the `2^53` boundary.\n- Handbook evidence record `EV-STRUCT-0011` (subjects `FUNC.ATAN2`, `FUNC.BASE`) — the array-lift\n  tranche, with a per-surface witness for `BASE` and counts that are group totals carrying a warning\n  against per-surface attribution.\n- Handbook projections `data/functions/FUNC.BASE.json` (arity 2-3, `Custom` coercion-lift and\n  kernel signature) and `data/presence/FUNC.BASE.json` (implementing module; the `BUG-FUNC-017`\n  array-lift defect stream).\n- Handbook [The value universe](../model/01-value-universe.md) (text as UTF-16 code units) and\n  [Coercion and lifting](../model/02-coercion-and-lifting.md).\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| 20430 | Windows, 64-bit, CPU not recorded | 3,560 |\n\nThe record contains no same-input comparison between these environments. Reading different inputs on different builds does not establish either a version change or cross-build agreement.\n\n[Recorded environments and comparison details](https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.BASE.json).",
    "what-it-does": "\n`BASE(number, radix, [min_length])` writes a non-negative integer in a positional numeral system\nof the given radix, and returns the result as **text**.\n\nFor an integer `n >= 0` and a radix `b >= 2`, the positional representation is the unique finite\nsequence of digits `d_k d_(k-1) ... d_1 d_0` with\n\n    n = sum over i of d_i * b^i,     0 <= d_i < b,     d_k != 0 (for n > 0)\n\nUniqueness is the theorem that makes the function well defined: for every `b >= 2` and every\n`n >= 0` there is exactly one such sequence. It fails for `b = 1` (no positional system exists) and\nfor `b = 0` (nothing exists), which is why those radices must be rejected rather than given some\nconvention.\n\nThe digits are extracted by the standard recurrence\n\n    d_i = floor(n / b^i) mod b,\n\nequivalently by repeated division: divide by `b`, record the remainder, repeat on the quotient\nuntil it is zero, and reverse. The number of digits is `floor(log_b n) + 1` for `n >= 1`, and `1`\nfor `n = 0`.\n\n**`min_length` pads on the left with zeros.** Microsoft's Learn reference documents the parameter as\n\"the minimum length of the returned string\" and states that if it is omitted, leading zeros are not\nadded. Padding never truncates: a representation longer than `min_length` is returned in full.\n\n\n\n### Arguments\n\n\n| Argument | Meaning | Required |\n|---|---|---|\n| `number` | The value to convert | yes |\n| `radix` | The base to convert into | yes |\n| `min_length` | Minimum width of the returned text, left-padded with zeros | no |\n\nThe misunderstood position is the **return kind**: `BASE` returns `Text`, not a number. `BASE(255,\n16)` is the string `\"FF\"`, and `BASE(9, 10)` is the string `\"9\"`, which will not compare equal to\nthe number `9` under `=`. Feeding a `BASE` result into arithmetic re-coerces it, and for radices\nother than 10 that coercion means something entirely different from the digits you wrote.\n\n\n"
  },
  "signature": {
    "display": "BASE(number, radix, [min_length])",
    "parameters": [
      {
        "description": null,
        "name": "number",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "radix",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "min_length",
        "optional": true,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 3,
        "min": 2
      },
      "category": "Math and trigonometry 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": "A number written as text in another base (radix 2 to 36)",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Converts a number into a text representation with the given radix (base)",
        "microsoft_url": "https://support.microsoft.com/en-us/office/base-function-2ef61411-aee9-4f29-a811-1c42456c6342"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "BASE"
        },
        {
          "locale": "bg-BG",
          "name": "BASE"
        },
        {
          "locale": "cs-CZ",
          "name": "BASE"
        },
        {
          "locale": "da-DK",
          "name": "BASIS"
        },
        {
          "locale": "de-DE",
          "name": "BASE"
        },
        {
          "locale": "el-GR",
          "name": "BASE"
        },
        {
          "locale": "en-AU",
          "name": "BASE"
        },
        {
          "locale": "en-GB",
          "name": "BASE"
        },
        {
          "locale": "en-US",
          "name": "BASE"
        },
        {
          "locale": "es-ES",
          "name": "BASE"
        },
        {
          "locale": "et-EE",
          "name": "BASE"
        },
        {
          "locale": "fi-FI",
          "name": "PERUS"
        },
        {
          "locale": "fr-FR",
          "name": "BASE*"
        },
        {
          "locale": "he-IL",
          "name": "BASE"
        },
        {
          "locale": "hr-HR",
          "name": "BASE"
        },
        {
          "locale": "hu-HU",
          "name": "ALAP"
        },
        {
          "locale": "id-ID",
          "name": "BASE"
        },
        {
          "locale": "it-IT",
          "name": "BASE"
        },
        {
          "locale": "ja-JP",
          "name": "BASE"
        },
        {
          "locale": "ko-KR",
          "name": "BASE"
        },
        {
          "locale": "lt-LT",
          "name": "BASE"
        },
        {
          "locale": "lv-LV",
          "name": "BASE"
        },
        {
          "locale": "nb-NO",
          "name": "BASE"
        },
        {
          "locale": "nl-NL",
          "name": "BASE"
        },
        {
          "locale": "pl-PL",
          "name": "PODSTAWA"
        },
        {
          "locale": "pt-BR",
          "name": "BASE"
        },
        {
          "locale": "pt-PT",
          "name": "BASE"
        },
        {
          "locale": "ro-RO",
          "name": "BASE"
        },
        {
          "locale": "ru-RU",
          "name": "ОСНОВАНИЕ"
        },
        {
          "locale": "sk-SK",
          "name": "BASE"
        },
        {
          "locale": "sl-SI",
          "name": "BASE"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "BASE"
        },
        {
          "locale": "sv-SE",
          "name": "BAS"
        },
        {
          "locale": "th-TH",
          "name": "BASE"
        },
        {
          "locale": "tr-TR",
          "name": "TABAN işlevi"
        },
        {
          "locale": "uk-UA",
          "name": "BASE"
        },
        {
          "locale": "vi-VN",
          "name": "BASE"
        },
        {
          "locale": "zh-CN",
          "name": "BASE"
        },
        {
          "locale": "zh-HK",
          "name": "BASE"
        },
        {
          "locale": "zh-TW",
          "name": "BASE"
        }
      ],
      "signature": {
        "display": "BASE(number, radix, [min_length])",
        "parameters": [
          {
            "description": null,
            "name": "number",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "radix",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "min_length",
            "optional": true,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "BASE",
      "version_marker": null,
      "xlcall": {
        "code": "571",
        "symbol": "xlfBase"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/base-function-2ef61411-aee9-4f29-a811-1c42456c6342"
  },
  "try_it": {
    "formula": "=BASE(255,16)"
  },
  "url": "https://handbook.dnacalc.com/functions/BASE.html",
  "variants": [],
  "versions": [
    {
      "behaviour": "3,560 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.BASE.json"
      ]
    }
  ]
}