{
  "category": "Math and trigonometry functions",
  "display_name": "SIGN",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.SIGN",
  "implementation_state": {
    "answer_bank": {
      "excel_builds": [
        "20430"
      ],
      "larger_numeric": 0,
      "last_bit": 0,
      "matched": 1224,
      "other_mismatch": 0,
      "refused": 2,
      "rows": 1226,
      "unread": 0,
      "worst_ulp": 0
    },
    "detail": "Of 1,364 recorded answers (1,226 in the answer bank and 138 workbook cells), 2 do not match: 2 are refused.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "differs",
    "state_label": "Known larger differences",
    "summary": "Refuses 2 of 1,364 recorded calls; the rest match",
    "workbook_corpus": {
      "cells": 138,
      "matched": 138
    }
  },
  "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#L105-L105",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/rounding.rs#L184-L198"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/rounding::call",
        "catalogue/rounding::numeric",
        "catalogue/rounding::numbers"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/rounding.rs#L105-L105",
      "state": "differs",
      "suite": null,
      "summary": "Refuses 2 of 1,364 recorded calls; the rest match"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.SIGN.json",
  "name": "SIGN",
  "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- **`ABS`** — the other half of the decomposition `x = SIGN(x) * ABS(x)`. The two are almost\n  always used together.\n- **`IF(x>0, 1, IF(x<0, -1, 0))`** — the hand-written equivalent, and worth mentioning because\n  it is the form readers write when they have forgotten `SIGN` exists. It also makes the\n  comparison semantics explicit, which `SIGN` hides.\n- **`GESTEP` and `DELTA`** (engineering category) — the other threshold functions. `DELTA(a, b)`\n  is an equality indicator and `GESTEP(x, step)` a step function; between them and `SIGN` there\n  are three different conventions for what happens exactly at the boundary, and they do not\n  agree with each other.\n- **`TANH`** — the smooth saturating analogue. Where `SIGN` is used to steer a computation,\n  `TANH(k*x)` for large `k` is the differentiable stand-in, which is why it turns up in\n  optimization work.\n- **`TRUNC`, `INT`, `ROUND`** — the rounding family shares `SIGN`'s sensitivity to which side of\n  zero a value falls on; `TRUNC` in particular is \"round toward zero\", i.e. rounding in the\n  direction opposite to `SIGN`.\n- **Confused with**: `ABS` (magnitude, not direction) and with a two-valued sign, which is what\n  most programming languages' bit-level helpers return.\n\n\n",
    "how-to-implement": "\n### Numerical notes\n\n\n`SIGN` performs no arithmetic, so it has no rounding error of its own. Everything that goes\nwrong with it goes wrong upstream, and there are three recurring patterns worth naming.\n\n**1. The zero case is almost never the zero you mean.** `SIGN(0.1 + 0.2 - 0.3)` is not `0`,\nbecause `0.1 + 0.2 - 0.3` is not `0` in binary64. Any workflow that uses `SIGN` to test \"did\nthis quantity come out to zero\" is testing an exact bit condition and will get `±1` on values\nthat are zero to any reasonable tolerance. The remedy is not to fix `SIGN`; it is to test\n`ABS(x) < tol` explicitly, so that the tolerance is visible in the formula rather than implied.\n\n**2. `SIGN` is a discontinuity amplifier.** Its condition number is infinite at the origin: an\narbitrarily small perturbation of the input changes the output by 1 or 2. That is inherent to\nthe mathematics, not a defect, but it means `SIGN` should never sit downstream of a long\naccumulation whose last bits are noise. The classic failure is a sign-change test on the\nresidual of an iterative calculation, where the residual's own error exceeds its value near\nconvergence — the bisection loop then wanders because `SIGN` is reporting the sign of the\nrounding error.\n\n**3. Sign-bit extraction and signum are different functions.** They agree everywhere except at\nzero, where signum gives `0` for both zeros and sign-bit extraction gives `+1`/`-1`\nrespectively. An implementation written with `copysign` or a bit mask gets the negative-zero\ncase wrong relative to the documented three-valued definition; an implementation written with\ntwo comparisons gets it right. Since the difference shows up on exactly one input class, it\nsurvives casual testing indefinitely. This is the reason the negative-zero probe below is worth\nrunning even though the case looks exotic.\n\n**What a careful implementation does**: two comparisons against literal zero, in the order\n`x > 0`, then `x < 0`, then `0`. Under IEEE comparison semantics this handles both zeros\ncorrectly and needs no special case. It is three lines and there is no cleverer version worth\nhaving.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns `Number`, one of `-1`, `0`, `1`.\n\n- **Zero.** The documented result is `0`. The interesting question is **negative zero**: IEEE\n  754 has two zeros, `+0` and `-0`, which compare equal to each other and to nothing else. Under\n  a comparison-based signum, `SIGN(-0)` is `0`; under a sign-bit-based one it would be `-1`.\n  Microsoft's page does not address the case. The Handbook does not assert an answer, and this\n  is the first probe listed below. Producing a `-0` argument in a worksheet is easy enough —\n  `-1 * 0`, or `0 * -1`, or a formula that underflows from below.\n- **Subnormals.** A subnormal is a nonzero number, so `SIGN` of one is `±1`. The documented\n  example `SIGN(-0.00001)` makes the general point: magnitude is irrelevant, only the sign\n  matters.\n\n\n\n### Errors\n\n\n| Error | Condition | Source |\n|---|---|---|\n| `#VALUE!` | The argument does not convert to a number | Shared coercion rules |\n| propagated | An error value in the argument is returned unchanged | Shared coercion rules |\n\nMicrosoft's page lists no error conditions for `SIGN`, and no domain restriction exists — the\nfunction is total on the reals.\n\n\n",
    "sources": "\n- Microsoft, \"SIGN function\" —\n  <https://support.microsoft.com/en-us/office/sign-function-109c932d-fcdc-4023-91f1-2dd0e916a1d8>\n  (signature, \"any real number\", the three-valued result, and the examples `SIGN(10)`,\n  `SIGN(4-4)`, `SIGN(-0.00001)`; no error conditions are listed).\n- IEEE 754-2019 — signed zero, comparison semantics, and the distinction between `isSignMinus`\n  and a mathematical signum.\n- Handbook projections `data/functions/FUNC.SIGN.json` (arity,\n  `kernel_signature_class: NumToNum`, `error_collapse_profile: None`, `real_result_policy` with\n  `arg_domain_guard=none` and `non_finite=allow`) and `data/presence/FUNC.SIGN.json`.\n- Handbook [The value universe](../model/01-value-universe.md) 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| 19929 | Windows, bitness not recorded, CPU not recorded | 40 |\n| 20430 | Windows, 64-bit, CPU not recorded | 1,226 |\n\n- XC-SIGN-001: 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.\n\nAgreement on these compared inputs does not establish agreement on unmeasured inputs.\n\n[Recorded environments and comparison details](https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.SIGN.json).",
    "what-it-does": "\n`SIGN(number)` is the **signum** function:\n\n    sgn(x) =  1  for x > 0\n              0  for x = 0\n             -1  for x < 0\n\nMicrosoft's page states exactly that: it \"Returns 1 if the number is positive, zero (0) if the\nnumber is 0, and -1 if the number is negative\", with `=SIGN(10)` giving 1, `=SIGN(4-4)` giving\n0, and `=SIGN(-0.00001)` giving -1.\n\n- **Domain**: all real numbers; the documentation says \"any real number\".\n- **Range**: the three-element set `{-1, 0, 1}`.\n- **Parity**: odd, `sgn(-x) = -sgn(x)`.\n- **Structure**: `sgn` is the derivative of `|x|` away from the origin, and `x = sgn(x) * |x|`\n  is the polar decomposition of a real number. `sgn` is discontinuous at `0` — the only\n  discontinuity, a jump of size 2 — and that single point is where every implementation question\n  lives.\n- **Identities worth having**: `SIGN(x) * ABS(x) = x`; `SIGN(x)^2` is `1` except at zero;\n  `ABS(SIGN(a) - SIGN(b))` is a sign-change detector, which is the classic bisection guard.\n\nThe three-valued convention is worth naming explicitly because it is not universal. Some\nlanguages define `sign` as two-valued (`±1`, with zero going to `+1`), and hardware sign-bit\nextraction is two-valued by construction. Excel's documented function is the three-valued\nmathematical signum.\n\n\n\n### Arguments\n\n\n| Argument | Meaning | Default |\n|---|---|---|\n| `number` | Any real number. Required. | — |\n\nThere is no tolerance argument and no epsilon. `SIGN` compares against exact zero, which is the\nsource of essentially every surprise it produces (see *Numerical notes*).\n\n\n"
  },
  "signature": {
    "display": "SIGN(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": "Math and trigonometry functions",
      "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": "1 for a positive number, 0 for zero, -1 for a negative number",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns the sign of a number",
        "microsoft_url": "https://support.microsoft.com/en-us/office/sign-function-109c932d-fcdc-4023-91f1-2dd0e916a1d8"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "SIGN"
        },
        {
          "locale": "bg-BG",
          "name": "SIGN"
        },
        {
          "locale": "cs-CZ",
          "name": "SIGN"
        },
        {
          "locale": "da-DK",
          "name": "FORTEGN"
        },
        {
          "locale": "de-DE",
          "name": "SIGN"
        },
        {
          "locale": "el-GR",
          "name": "SIGN"
        },
        {
          "locale": "en-AU",
          "name": "SIGN"
        },
        {
          "locale": "en-GB",
          "name": "SIGN"
        },
        {
          "locale": "en-US",
          "name": "SIGN"
        },
        {
          "locale": "es-ES",
          "name": "SIGNO"
        },
        {
          "locale": "et-EE",
          "name": "SIGN"
        },
        {
          "locale": "fi-FI",
          "name": "ETUMERKKI"
        },
        {
          "locale": "fr-FR",
          "name": "SIGNE*"
        },
        {
          "locale": "he-IL",
          "name": "SIGN"
        },
        {
          "locale": "hr-HR",
          "name": "SIGN"
        },
        {
          "locale": "hu-HU",
          "name": "ELŐJEL"
        },
        {
          "locale": "id-ID",
          "name": "SIGN"
        },
        {
          "locale": "it-IT",
          "name": "SEGNO"
        },
        {
          "locale": "ja-JP",
          "name": "SIGN"
        },
        {
          "locale": "ko-KR",
          "name": "SIGN"
        },
        {
          "locale": "lt-LT",
          "name": "SIGN"
        },
        {
          "locale": "lv-LV",
          "name": "SIGN"
        },
        {
          "locale": "nb-NO",
          "name": "SIGN"
        },
        {
          "locale": "nl-NL",
          "name": "SIGN"
        },
        {
          "locale": "pl-PL",
          "name": "ZNAK.LICZBY"
        },
        {
          "locale": "pt-BR",
          "name": "SIGN"
        },
        {
          "locale": "pt-PT",
          "name": "SINAL"
        },
        {
          "locale": "ro-RO",
          "name": "SIGN"
        },
        {
          "locale": "ru-RU",
          "name": "SIGN"
        },
        {
          "locale": "sk-SK",
          "name": "SIGN"
        },
        {
          "locale": "sl-SI",
          "name": "SIGN"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "ZNAK"
        },
        {
          "locale": "sv-SE",
          "name": "TECKEN"
        },
        {
          "locale": "th-TH",
          "name": "SIGN"
        },
        {
          "locale": "tr-TR",
          "name": "İŞARET"
        },
        {
          "locale": "uk-UA",
          "name": "SIGN"
        },
        {
          "locale": "vi-VN",
          "name": "SIGN"
        },
        {
          "locale": "zh-CN",
          "name": "SIGN"
        },
        {
          "locale": "zh-HK",
          "name": "SIGN"
        },
        {
          "locale": "zh-TW",
          "name": "SIGN"
        }
      ],
      "signature": {
        "display": "SIGN(number)",
        "parameters": [
          {
            "description": null,
            "name": "number",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "SIGN",
      "version_marker": null,
      "xlcall": {
        "code": "26",
        "symbol": "xlfSign"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/sign-function-109c932d-fcdc-4023-91f1-2dd0e916a1d8"
  },
  "try_it": {
    "formula": "=SIGN(10)"
  },
  "url": "https://handbook.dnacalc.com/functions/SIGN.html",
  "variants": [],
  "versions": [
    {
      "behaviour": "40 captured inputs are indexed for this environment. Capture dates are not recorded. This is a reading count, not a comparison with another build.",
      "excel_build": "16.0 build 19929",
      "platform": "Windows, bitness not recorded, CPU not recorded",
      "sources": [
        "https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.SIGN.json"
      ]
    },
    {
      "behaviour": "1,226 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.SIGN.json"
      ]
    }
  ]
}