{
  "category": "Operators",
  "display_name": "Percentage (%)",
  "entry_kind": "built_in_operator",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.OP_PERCENT",
  "implementation_state": {
    "answer_bank": null,
    "detail": "",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "unmeasured",
    "state_label": "Implemented, no recorded answers attributed to it",
    "summary": "Implemented; no recorded answers are attributed to this entry",
    "workbook_corpus": null
  },
  "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/arithmetic.rs#L45-L45",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/arithmetic.rs#L199-L211"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/arithmetic::divide",
        "catalogue/arithmetic::flushed",
        "catalogue/arithmetic::binary",
        "catalogue/arithmetic::operands"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/arithmetic.rs#L45-L45",
      "state": "unmeasured",
      "suite": null,
      "summary": "Implemented; no recorded answers are attributed to this entry"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.OP_PERCENT.json",
  "name": "OP_PERCENT",
  "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- [`FUNC.OP_DIVIDE`](FUNC.OP_DIVIDE.md) and [`FUNC.OP_MULTIPLY`](FUNC.OP_MULTIPLY.md) — the\n  two operators `%` might be implemented in terms of, and the reason the ambiguity above\n  matters.\n- [`FUNC.OP_NEGATE`](FUNC.OP_NEGATE.md), [`FUNC.OP_UNARY_PLUS`](FUNC.OP_UNARY_PLUS.md) — the\n  other unary members of the family.\n- `PERCENTILE`, `PERCENTRANK`, `PERCENTOF` — statistical functions whose names share the word\n  and share nothing else.\n- `TEXT(x, \"0%\")` — the formatting route. If the goal is display, `%`-the-operator is the\n  wrong tool; if the goal is arithmetic, the format is.\n\n\n",
    "how-to-implement": "\n### Notes for implementers\n\n\n- Pick a spelling and record which one: `x / 100` or `x * 0.01`. They are not the same\n  function of a double, and a compatibility implementation that guesses will disagree with\n  Excel on some operands. The Handbook cannot yet tell you which to pick.\n- Do not implement `%` by string manipulation of the formula or by adjusting the cell format.\n  It is a value transformation.\n- Chained application (`A%%`) must scale twice; there is no idempotence to exploit.\n- The elementwise array path must preserve element-local failures.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n- **Text and logical operands.** Shared to-number rules from\n  [coercion and lifting](../model/02-coercion-and-lifting.md). Note the overlap: chapter 02\n  records that Excel's text-to-number recognizer itself accepts percent signs in some\n  locale-dependent forms, so `\"50%\"` as *text* may already convert to `0.5` before this\n  operator is reached — and `\"50%\"%` would then scale it again. That interaction is\n  unrecorded here and is a good probe.\n- **Empty and omitted.** Per-family policy under chapter 02; unrecorded for this row.\n- **Arrays.** `CoercionLiftProfile::UnaryNumericScalarOrArrayElementwise` — mapped\n  elementwise, with element-local failures.\n- **Underflow.** Scaling a subnormal by a hundredth flushes it toward zero; scaling any tiny\n  value repeatedly reaches zero. Nothing about this is specific to `%`, but `%` is a cheap way\n  to reach the subnormal range from ordinary-looking data.\n- **Overflow.** Not reachable: scaling down cannot overflow.\n\n\n",
    "sources": "- `data/presence/FUNC.OP_PERCENT.json` — implementing module\n  `earlier-implementation/operator_arithmetic_family.rs`.\n- Handbook `content/model/01-value-universe.md` (numbers wearing formats),\n  `02-coercion-and-lifting.md` (the locale-dependent recognizer note),\n  `03-call-pipeline.md`.\n\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`A%` converts its operand to a number and returns that number scaled by one hundredth. `50%`\nis `0.5`; `A1%` is a hundredth of whatever `A1` holds.\n\nThe interesting content is in the word \"scaled\", because binary64 gives two inequivalent\nspellings of it:\n\n- `x / 100` — divide by an exactly representable integer, one rounding.\n- `x * 0.01` — multiply by the double nearest to one hundredth, which is *not* one hundredth,\n  and then round.\n\nThese do not agree for every `x`. The literal `0.01` is already a rounded approximation, so\nthe multiplication rounds twice in effect; the division rounds once against an exact divisor\nand is the more accurate of the two. For most operands both spellings land on the same\ndouble, and for some they do not — which makes this a real, if small, last-bit question about\na function whose definition looks trivial.\n\nThe percent *format* is a separate thing entirely. Formatting a cell as a percentage changes\nhow a number is displayed and how typed input is interpreted by the host; `%` as an operator\nchanges the value. A cell holding `0.5` formatted as a percentage shows `50%` without this\noperator ever running. Chapter 01's rule applies: dates, currency and percentages are numbers\nwearing formats.\n\n\n\n### Arguments\n\n\n| Position | Name | Meaning |\n|---|---|---|\n| 0 | `A` | The operand to scale. Required. |\n\nArity is exactly 1; no optional arguments, no defaults. The operator is postfix — it follows\nits operand — which makes it the only member of the arithmetic family with that shape.\n\nPostfix position raises a precedence question (`-2%`, `2^3%`, `2%%`) that this Handbook does\nnot answer: formula grammar and precedence are explicitly out of scope (`CHARTER.md` section\n4), and the operator-inventory decision register in the sources records precedence ownership\nas an open item. What the Handbook *can* say is that `%` is a one-argument function of a\nvalue, and that chaining it (`A%%`) applies it twice.\n\n\n"
  },
  "signature": {
    "display": "number%",
    "parameters": [
      {
        "description": null,
        "name": "number",
        "optional": false,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 1,
        "min": 1
      },
      "category": "Operators",
      "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": null,
        "short_source": "no-short-description"
      },
      "docs": null,
      "entry_kind": "built_in_operator",
      "localized_family_names": null,
      "localized_names": [],
      "signature": {
        "display": "number%",
        "parameters": [
          {
            "description": null,
            "name": "number",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "OP_PERCENT",
      "version_marker": null,
      "xlcall": null
    },
    "microsoft": null
  },
  "try_it": {
    "formula": "=25%"
  },
  "url": "https://handbook.dnacalc.com/functions/OP_PERCENT.html",
  "variants": [],
  "versions": []
}