{
  "category": "Math and trigonometry functions",
  "display_name": "MOD",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.MOD",
  "implementation_state": {
    "answer_bank": {
      "excel_builds": [
        "20430"
      ],
      "larger_numeric": 0,
      "last_bit": 0,
      "matched": 152432,
      "other_mismatch": 0,
      "refused": 0,
      "rows": 152432,
      "unread": 0,
      "worst_ulp": 0
    },
    "detail": "Recorded: 152,432 in the answer bank and 237 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 152,669 recorded answers",
    "workbook_corpus": {
      "cells": 237,
      "matched": 237
    }
  },
  "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/rounding.rs#L114-L114",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/rounding.rs#L602-L647",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/rounding.rs#L649-L674"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/rounding::call",
        "catalogue/rounding::numeric",
        "catalogue/rounding::numbers",
        "catalogue/rounding::abs",
        "catalogue/rounding::quotient",
        "decimal::truncate"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/rounding.rs#L114-L114",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 152,669 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.MOD.json",
  "name": "MOD",
  "notes": [
    {
      "basis": "All 152,432 recorded MOD rows match, 4,974 of them rows the ordinary step misses, and so do 1,128 new Excel readings (build 20527). Those readings overturned an earlier test on power-of-two divisors: 1E-296 behaves like a power of two and 1E-300 does not.",
      "documentation": null,
      "evidence": [
        {
          "commit": "ab94fb91a50fbdf89bdb2dac0e12fcd77a5e5f82",
          "locator": null,
          "note": "the rules in the product; the commit message carries the row counts",
          "path": "crates/calc-func/src/catalogue/rounding.rs",
          "repository": "DnaCalc"
        },
        {
          "commit": "b5d84a80a5a4640eca9ce04f232c0bc115503f34",
          "locator": null,
          "note": "research write-up: full-bank result, the rules, what stays open",
          "path": "content/notes/evidence/2026-11-04/rounding-EVIDENCE.md",
          "repository": "ExcelFunctionsHandbook"
        }
      ],
      "functions": [
        "FUNC.MOD"
      ],
      "inferred": "The rule is what is measured. Reading it as Veltkamp's split, the parts of a Dekker product of the count and the divisor, is an interpretation: a table over exponent and trailing zeros puts the boundary between exponents -1000 and -990 and at about 27 trailing zeros.",
      "kind": "excel-differs-from-math",
      "note_id": "FN-MOD-001",
      "open": [],
      "recorded_on": "2026-11-04",
      "repros": [
        {
          "call": "MOD(-1.223247290044572e-296, 1.223247290044539e-296)",
          "correct": {
            "bits": "0x027fffffffffff0e",
            "display": "1.2232472900445062e-296",
            "how": "MOD(n,d) = n - d*INT(n/d) in exact rational arithmetic; the result is exactly representable.",
            "kind": "number"
          },
          "excel": {
            "bits": "0x0280000000000079",
            "display": "1.223247290044572e-296",
            "kind": "number"
          },
          "input_route": "cell-value2",
          "inputs": [
            {
              "name": "number",
              "value": {
                "bits": "0x8280000000000079",
                "display": "-1.223247290044572e-296",
                "kind": "number"
              }
            },
            {
              "name": "divisor",
              "value": {
                "bits": "0x0280000000000000",
                "display": "1.223247290044539e-296",
                "kind": "number"
              }
            }
          ],
          "recorded_in": "Excel 16.0 build 20430, Windows 64-bit, CPU not recorded in this capture",
          "source": {
            "commit": "4d5320dfdc385354469b4d506153357bb932ab08",
            "locator": "w111mod-tiny-discriminator-00960",
            "note": null,
            "path": "runs/w111-mod-tiny-discriminator-20260929/answers-mod.json.gz",
            "repository": "CalcFunc-Evidence"
          }
        },
        {
          "call": "MOD(1.223247290044539e-296, -1.2232472900445716e-296)",
          "correct": {
            "bits": "0x80003c0000000000",
            "display": "-3.25938553492266e-310",
            "how": "MOD(n,d) = n - d*INT(n/d) in exact rational arithmetic; the result is exactly representable.",
            "kind": "number"
          },
          "excel": {
            "bits": null,
            "display": "#NUM!",
            "kind": "error"
          },
          "input_route": "cell-value2",
          "inputs": [
            {
              "name": "number",
              "value": {
                "bits": "0x0280000000000000",
                "display": "1.223247290044539e-296",
                "kind": "number"
              }
            },
            {
              "name": "divisor",
              "value": {
                "bits": "0x8280000000000078",
                "display": "-1.2232472900445716e-296",
                "kind": "number"
              }
            }
          ],
          "recorded_in": "Excel 16.0 build 20430, Windows 64-bit, CPU not recorded in this capture",
          "source": {
            "commit": "4d5320dfdc385354469b4d506153357bb932ab08",
            "locator": "w111mod-tiny-discriminator-00959",
            "note": null,
            "path": "runs/w111-mod-tiny-discriminator-20260929/answers-mod.json.gz",
            "repository": "CalcFunc-Evidence"
          }
        }
      ],
      "schema": "efh.function-note/v1",
      "statement": "MOD(n,d) takes the exact remainder r of n by d and adds d when their signs differ. Three things change when r is subnormal and its sign differs from d's. The result is #NUM! when |n/d| is 2^26 or more, or when d's low part under a Veltkamp split at 2^27 + 1 is subnormal. Otherwise, when |r| is below 2^-1026, the result is |d| + |r| with d's sign: the remainder is added where it should be taken away. A larger r takes the ordinary step. Any subnormal final result is #NUM!. So MOD(-(1+121*2^-52)*2^-983, 2^-983) returns +(1+121*2^-52)*2^-983, and MOD(2^-983, -(1+120*2^-52)*2^-983) returns #NUM!, where the exact answers are ordinary numbers.",
      "status": "measured",
      "title": "MOD with tiny operands gives wrong signs and #NUM!, by a rule that fits every recorded row"
    }
  ],
  "schema": "efh.function-reference/v1",
  "section_order": [
    "what-it-does",
    "try-it",
    "quirks",
    "how-to-implement",
    "version-differences",
    "alternatives"
  ],
  "sections": {
    "alternatives": "\n[QUOTIENT](FUNC.QUOTIENT.md) truncates the quotient, so pairing it with MOD does not reconstruct mixed-sign inputs. [INT](FUNC.INT.md) supplies the floor convention; a language’s `%` may use another convention.\n\n\n\n\n",
    "how-to-implement": "\nUse `R(op)` as defined in the [stored arithmetic recipe](FUNC.VAR.S.md#how-to-implement).\n\n1. Coerce both arguments, reject a zero divisor, and return zero for a zero dividend. Compute `q=R(number/divisor)`; reject `abs(q)>=1.1259e12` or a nonfinite quotient.\n2. Compute the **truncating** binary64 remainder `r`, using a correctly implemented `fmod` primitive or integer significand/exponent reduction. Do not compute `number-divisor*floor(q)` in floating point: that can lose the small remainder.\n3. If `r` is nonzero and has the divisor’s opposite sign, normally set `v=R(r+divisor)`. If that addition rounds exactly to the divisor, the current compatibility rule returns zero.\n4. Before that addition, a **subnormal** `r` of the opposite sign needs a special branch. With `a=abs(divisor)` and ordinary binary64 operations, set `c=(2^27+1)*a`, `low=a-(c-(c-a))`. A subnormal `low`, or `abs(q)>=2^26`, gives `#NUM!`. Otherwise, if `abs(r)<2^-1026`, return `R(a+abs(r))` with the divisor’s sign. A larger remainder takes the normal addition.\n5. If no sign adjustment is needed, keep `r`. Any subnormal final result is `#NUM!`.\n\nWorked ordinary path: `fmod(-7,3)=-1`; the signs differ, so `-1+3=2`. Worked large-quotient refusal: `MOD(1125899999999,1)` is recorded as zero, while `MOD(1125900000000,1)` is `#NUM!`.\n\nTo implement the truncating remainder without a host `fmod`, decode the positive magnitudes as `Mx*2^Ex` and `My*2^Ey`, with integer significands. Set `E=min(Ex,Ey)`, `A=Mx << (Ex-E)` and `B=My << (Ey-E)`. Take the integer remainder `U=A mod B`, then restore the dividend's sign to `U*2^E`. Arbitrary-size integers make the shifts and remainder exact. This is a separate calculation from the rounded quotient used by the rejection test; do not reuse that quotient to reconstruct the remainder.\n\nFor `10` and binary64 `0.1`, choose the common unit `2^-56`. The integers are `A=720575940379279360` and `B=7205759403792794`. Integer division gives quotient 99 and remainder `7205759403792754`. Rescaling that remainder gives `0.09999999999999945`. Rounding the quotient to 100 before subtracting would erase the answer this function records.\n\nWorked tiny path: inputs `-1.223247290044572e-296` and `1.223247290044539e-296` have an opposite-sign subnormal remainder. The recorded special branch adds its magnitude and returns `1.223247290044572e-296`, larger than the divisor. The mathematically correct remainder is `1.2232472900445062e-296`. The note retains input and result bits.\n\nThe rule matches the cited recorded bank and fresh probes. Interpreting the split as evidence of a Dekker product is an inference; the measured rule does not reveal Microsoft’s private implementation.\n\n\n",
    "quirks": "\nA zero divisor gives `#DIV/0!`. Recorded Excel returns `#NUM!` when the rounded quotient magnitude reaches `1.1259e12`, although a mathematical remainder still exists. Tiny operands can return the wrong sign-adjusted magnitude or `#NUM!`; these are compatibility rules, not properties of mathematical modulo. The prior explanation that Excel necessarily subtracts two large approximate products is not supported by the later exact-remainder evidence.\n\n\n",
    "sources": "\n- [Microsoft: MOD function](https://support.microsoft.com/en-us/excel/functions/mod-function), opened 6 November 2026; syntax, documented argument rules and errors.\n- [DnaCalc implementation](https://github.com/DnaCalc/DnaCalc/blob/da3ecc4fb19a3a5529708c311d0e8f05688ac165/crates/calc-func/src/catalogue/rounding.rs); implementation steps and the limits identified in the text.\n- [FN-MOD-001](../notes/FN-MOD-001.json): exact tiny-operand counterexamples and their scope.\n\n",
    "try-it": "\n`=MOD(-7,3)` returns `2`: `-7 = (-3)*3+2`. `=MOD(7,-3)` returns `-2`. With binary64 decimal inputs, the recorded `MOD(10,0.1)` is `0.09999999999999945`, not zero.\n\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 | 105 |\n| 20430 | Windows, 64-bit, CPU not recorded | 152,432 |\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.MOD.json).\n\nRetained controls from the indexed captures:\n\n| Build and recorded CPU | Captured call or arguments | Excel result |\n|---|---|---|\n| 19929, CPU not recorded | [`=MOD(-32.02542717687437346,1.00000000000000000)`](https://github.com/DnaCalc/CalcFunc-Evidence/blob/4287ba192d2e3a7fd54671ea1cee1c34cb2e84e2/runs/W097-R-B-validation-cellref-module/comparisons/excel_sample_comparisons.jsonl.gz) | `0.9745728231256265` (`0x3fef2fb3585ca380`) |\n| 20430, CPU not recorded | [`MOD(1,2)`](https://github.com/DnaCalc/CalcFunc-Evidence/blob/4287ba192d2e3a7fd54671ea1cee1c34cb2e84e2/cache/w111-broad-regenerated-20260929/answers-mod.json.gz) | `1` (`0x3ff0000000000000`) |\n\nThese are earlier recorded answers, not new Excel runs or an additional cross-build comparison. The function JSON retains each source locator, exact argument bits where available, and input-route status. Call notation does not imply that captured binary64 values were entered as decimal formula literals.",
    "what-it-does": "\n`MOD(number, divisor)` returns the floored remainder. For ordinary nonzero remainders the result follows the divisor’s sign. Noninteger inputs are allowed. The mathematical identity is `number-divisor*INT(number/divisor)`.\n\n\n"
  },
  "signature": {
    "display": "MOD(number, divisor)",
    "parameters": [
      {
        "description": null,
        "name": "number",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "divisor",
        "optional": false,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 2,
        "min": 2
      },
      "category": "Math and trigonometry functions",
      "classification": {
        "arg_preparation_profile": "ValuesOnlyPreAdapter",
        "coercion_lift_profile": "UnaryNumericScalarOnly",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "None",
        "fec_dependency_profile": "None",
        "host_interaction_class": "None",
        "kernel_signature_class": "NumsToNum",
        "rich_value_usage": "RichBlind",
        "surface_fec_dependency_profile": "RefOnly",
        "thread_safety_class": "SafePure",
        "volatility_class": "NonVolatile"
      },
      "descriptions": {
        "long": null,
        "short": "Remainder after division, with the sign of the divisor",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns the remainder from division",
        "microsoft_url": "https://support.microsoft.com/en-us/office/mod-function-9b6cd169-b6ee-406a-a97b-edf2a9dc24f3"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "MOD"
        },
        {
          "locale": "bg-BG",
          "name": "MOD"
        },
        {
          "locale": "cs-CZ",
          "name": "MOD"
        },
        {
          "locale": "da-DK",
          "name": "REST"
        },
        {
          "locale": "de-DE",
          "name": "REST"
        },
        {
          "locale": "el-GR",
          "name": "MOD"
        },
        {
          "locale": "en-AU",
          "name": "MOD"
        },
        {
          "locale": "en-GB",
          "name": "MOD"
        },
        {
          "locale": "en-US",
          "name": "MOD"
        },
        {
          "locale": "es-ES",
          "name": "RESIDUO"
        },
        {
          "locale": "et-EE",
          "name": "MOD"
        },
        {
          "locale": "fi-FI",
          "name": "JAKOJ"
        },
        {
          "locale": "fr-FR",
          "name": "MOD"
        },
        {
          "locale": "he-IL",
          "name": "MOD"
        },
        {
          "locale": "hr-HR",
          "name": "MOD"
        },
        {
          "locale": "hu-HU",
          "name": "MARADÉK"
        },
        {
          "locale": "id-ID",
          "name": "MOD"
        },
        {
          "locale": "it-IT",
          "name": "MOD"
        },
        {
          "locale": "ja-JP",
          "name": "MOD"
        },
        {
          "locale": "ko-KR",
          "name": "MOD"
        },
        {
          "locale": "lt-LT",
          "name": "MOD"
        },
        {
          "locale": "lv-LV",
          "name": "MOD"
        },
        {
          "locale": "nb-NO",
          "name": "MOD"
        },
        {
          "locale": "nl-NL",
          "name": "REST"
        },
        {
          "locale": "pl-PL",
          "name": "MOD"
        },
        {
          "locale": "pt-BR",
          "name": "MOD"
        },
        {
          "locale": "pt-PT",
          "name": "RESTO"
        },
        {
          "locale": "ro-RO",
          "name": "MOD"
        },
        {
          "locale": "ru-RU",
          "name": "ОСТАТ"
        },
        {
          "locale": "sk-SK",
          "name": "MOD"
        },
        {
          "locale": "sl-SI",
          "name": "MOD"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "MOD"
        },
        {
          "locale": "sv-SE",
          "name": "MOD"
        },
        {
          "locale": "th-TH",
          "name": "MOD"
        },
        {
          "locale": "tr-TR",
          "name": "MOD"
        },
        {
          "locale": "uk-UA",
          "name": "MOD"
        },
        {
          "locale": "vi-VN",
          "name": "MOD"
        },
        {
          "locale": "zh-CN",
          "name": "MOD"
        },
        {
          "locale": "zh-HK",
          "name": "MOD"
        },
        {
          "locale": "zh-TW",
          "name": "MOD"
        }
      ],
      "signature": {
        "display": "MOD(number, divisor)",
        "parameters": [
          {
            "description": null,
            "name": "number",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "divisor",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "MOD",
      "version_marker": null,
      "xlcall": {
        "code": "39",
        "symbol": "xlfMod"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/mod-function-9b6cd169-b6ee-406a-a97b-edf2a9dc24f3"
  },
  "try_it": {
    "formula": "=MOD(-7,3)"
  },
  "url": "https://handbook.dnacalc.com/functions/MOD.html",
  "variants": [],
  "versions": [
    {
      "behaviour": "MOD(-1.223247290044572e-296, 1.223247290044539e-296) returned 1.223247290044572e-296 (0x0280000000000079). MOD(1.223247290044539e-296, -1.2232472900445716e-296) returned #NUM!. Inputs were supplied through cells using Value2. These are controls from this environment, not a same-input comparison with another build.",
      "excel_build": "16.0 build 20430",
      "observations": [
        {
          "call": "MOD(-1.223247290044572e-296, 1.223247290044539e-296)",
          "excel": {
            "bits": "0x0280000000000079",
            "display": "1.223247290044572e-296",
            "kind": "number"
          },
          "input_route": "cell-value2",
          "inputs": [
            {
              "name": "number",
              "value": {
                "bits": "0x8280000000000079",
                "display": "-1.223247290044572e-296",
                "kind": "number"
              }
            },
            {
              "name": "divisor",
              "value": {
                "bits": "0x0280000000000000",
                "display": "1.223247290044539e-296",
                "kind": "number"
              }
            }
          ],
          "recorded_in": "Excel 16.0 build 20430, Windows 64-bit, CPU not recorded in this capture"
        },
        {
          "call": "MOD(1.223247290044539e-296, -1.2232472900445716e-296)",
          "excel": {
            "bits": null,
            "display": "#NUM!",
            "kind": "error"
          },
          "input_route": "cell-value2",
          "inputs": [
            {
              "name": "number",
              "value": {
                "bits": "0x0280000000000000",
                "display": "1.223247290044539e-296",
                "kind": "number"
              }
            },
            {
              "name": "divisor",
              "value": {
                "bits": "0x8280000000000078",
                "display": "-1.2232472900445716e-296",
                "kind": "number"
              }
            }
          ],
          "recorded_in": "Excel 16.0 build 20430, Windows 64-bit, CPU not recorded in this capture"
        }
      ],
      "platform": "Windows 64-bit, CPU not recorded in this capture",
      "sources": [
        "https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/3345a87/content/notes/FN-MOD-001.json"
      ]
    },
    {
      "behaviour": "105 captured inputs are indexed for this environment. Capture dates are not recorded. This is a reading count, not a comparison with another build. Retained control =MOD(-32.02542717687437346,1.00000000000000000) returned 0.9745728231256265 (0x3fef2fb3585ca380). The selected archive row does not record its input plumbing; no input route is inferred.",
      "excel_build": "16.0 build 19929",
      "observations": [
        {
          "call": "=MOD(-32.02542717687437346,1.00000000000000000)",
          "excel": {
            "bits": "0x3fef2fb3585ca380",
            "display": "0.9745728231256265",
            "kind": "number"
          },
          "input_route": "not-recorded",
          "inputs": [],
          "recorded_in": "Excel 16.0 build 19929, Windows, bitness not recorded, CPU not recorded.",
          "source": {
            "commit": "4287ba192d2e3a7fd54671ea1cee1c34cb2e84e2",
            "locator": "BSE-000000360",
            "path": "runs/W097-R-B-validation-cellref-module/comparisons/excel_sample_comparisons.jsonl.gz",
            "repository": "CalcFunc-Evidence"
          }
        }
      ],
      "platform": "Windows, bitness not recorded, CPU not recorded",
      "sources": [
        "https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.MOD.json",
        "https://github.com/DnaCalc/CalcFunc-Evidence/blob/4287ba192d2e3a7fd54671ea1cee1c34cb2e84e2/runs/W097-R-B-validation-cellref-module/comparisons/excel_sample_comparisons.jsonl.gz"
      ]
    },
    {
      "behaviour": "152,432 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. Retained control MOD(1,2) returned 1 (0x3ff0000000000000). The capture specifies exact-double bulk Value2 cell input.",
      "excel_build": "16.0 build 20430",
      "observations": [
        {
          "call": "MOD(1,2)",
          "excel": {
            "bits": "0x3ff0000000000000",
            "display": "1",
            "kind": "number"
          },
          "input_route": "cell-value2",
          "inputs": [
            {
              "name": "argument1",
              "value": {
                "bits": "0x3ff0000000000000",
                "display": "1",
                "kind": "number"
              }
            },
            {
              "name": "argument2",
              "value": {
                "bits": "0x4000000000000000",
                "display": "2",
                "kind": "number"
              }
            }
          ],
          "recorded_in": "Excel 16.0 build 20430, Windows, 64-bit, CPU not recorded.",
          "source": {
            "commit": "4287ba192d2e3a7fd54671ea1cee1c34cb2e84e2",
            "locator": "w111broad-20260929-MOD-00077",
            "path": "cache/w111-broad-regenerated-20260929/answers-mod.json.gz",
            "repository": "CalcFunc-Evidence"
          }
        }
      ],
      "platform": "Windows, 64-bit, CPU not recorded",
      "sources": [
        "https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.MOD.json",
        "https://github.com/DnaCalc/CalcFunc-Evidence/blob/4287ba192d2e3a7fd54671ea1cee1c34cb2e84e2/cache/w111-broad-regenerated-20260929/answers-mod.json.gz"
      ]
    }
  ]
}