Excel 16.0 build 19929
Windows, bitness not recorded, CPU not recorded
40 captured inputs are indexed for this environment. Capture dates are not recorded. This is a reading count, not a comparison with another build.
Math and trigonometry functions
Refuses 2 of 1,364 recorded calls; the rest match
Of 1,364 recorded answers (1,226 in the answer bank and 138 workbook cells), 2 do not match: 2 are refused. How we measure this · See the Rust code
| Language | Name in Excel |
|---|---|
| Arabic | SIGN |
| Bulgarian | SIGN |
| Czech | SIGN |
| Danish | FORTEGN |
| German | SIGN |
| Greek | SIGN |
| English (Australia) | SIGN |
| English (United Kingdom) | SIGN |
| English (United States) | SIGN |
| Spanish | SIGNO |
| Estonian | SIGN |
| Finnish | ETUMERKKI |
| French | SIGNE |
| Hebrew | SIGN |
| Croatian | SIGN |
| Hungarian | ELŐJEL |
| Indonesian | SIGN |
| Italian | SEGNO |
| Japanese | SIGN |
| Korean | SIGN |
| Lithuanian | SIGN |
| Latvian | SIGN |
| Norwegian | SIGN |
| Dutch | SIGN |
| Polish | ZNAK.LICZBY |
| Portuguese (Brazil) | SIGN |
| Portuguese (Portugal) | SINAL |
| Romanian | SIGN |
| Russian | SIGN |
| Slovak | SIGN |
| Slovenian | SIGN |
| Serbian (Latin) | ZNAK |
| Swedish | TECKEN |
| Thai | SIGN |
| Turkish | İŞARET |
| Ukrainian | SIGN |
| Vietnamese | SIGN |
| Chinese (Simplified) | SIGN |
| Chinese (Hong Kong) | SIGN |
| Chinese (Traditional) | SIGN |
Names from Microsoft's support site.
SIGN(number)
SIGN(number) is the signum function:
sgn(x) = 1 for x > 0
0 for x = 0
-1 for x < 0
Microsoft's page states exactly that: it "Returns 1 if the number is positive, zero (0) if the
number is 0, and -1 if the number is negative", with =SIGN(10) giving 1, =SIGN(4-4) giving
0, and =SIGN(-0.00001) giving -1.
{-1, 0, 1}.sgn(-x) = -sgn(x).sgn is the derivative of |x| away from the origin, and x = sgn(x) * |x|
is the polar decomposition of a real number. sgn is discontinuous at 0 — the only
discontinuity, a jump of size 2 — and that single point is where every implementation question
lives.SIGN(x) * ABS(x) = x; SIGN(x)^2 is 1 except at zero;
ABS(SIGN(a) - SIGN(b)) is a sign-change detector, which is the classic bisection guard.The three-valued convention is worth naming explicitly because it is not universal. Some
languages define sign as two-valued (±1, with zero going to +1), and hardware sign-bit
extraction is two-valued by construction. Excel's documented function is the three-valued
mathematical signum.
| Argument | Meaning | Default |
|---|---|---|
number | Any real number. Required. | — |
There is no tolerance argument and no epsilon. SIGN compares against exact zero, which is the
source of essentially every surprise it produces (see Numerical notes).
Returns Number, one of -1, 0, 1.
0. The interesting question is negative zero: IEEE
754 has two zeros, +0 and -0, which compare equal to each other and to nothing else. Under
a comparison-based signum, SIGN(-0) is 0; under a sign-bit-based one it would be -1.
Microsoft's page does not address the case. The Handbook does not assert an answer, and this
is the first probe listed below. Producing a -0 argument in a worksheet is easy enough —
-1 * 0, or 0 * -1, or a formula that underflows from below.SIGN of one is ±1. The documented
example SIGN(-0.00001) makes the general point: magnitude is irrelevant, only the sign
matters.| Error | Condition | Source |
|---|---|---|
#VALUE! | The argument does not convert to a number | Shared coercion rules |
| propagated | An error value in the argument is returned unchanged | Shared coercion rules |
Microsoft's page lists no error conditions for SIGN, and no domain restriction exists — the
function is total on the reals.
SIGN performs no arithmetic, so it has no rounding error of its own. Everything that goes
wrong with it goes wrong upstream, and there are three recurring patterns worth naming.
1. The zero case is almost never the zero you mean. SIGN(0.1 + 0.2 - 0.3) is not 0,
because 0.1 + 0.2 - 0.3 is not 0 in binary64. Any workflow that uses SIGN to test "did
this quantity come out to zero" is testing an exact bit condition and will get ±1 on values
that are zero to any reasonable tolerance. The remedy is not to fix SIGN; it is to test
ABS(x) < tol explicitly, so that the tolerance is visible in the formula rather than implied.
2. SIGN is a discontinuity amplifier. Its condition number is infinite at the origin: an
arbitrarily small perturbation of the input changes the output by 1 or 2. That is inherent to
the mathematics, not a defect, but it means SIGN should never sit downstream of a long
accumulation whose last bits are noise. The classic failure is a sign-change test on the
residual of an iterative calculation, where the residual's own error exceeds its value near
convergence — the bisection loop then wanders because SIGN is reporting the sign of the
rounding error.
3. Sign-bit extraction and signum are different functions. They agree everywhere except at
zero, where signum gives 0 for both zeros and sign-bit extraction gives +1/-1
respectively. An implementation written with copysign or a bit mask gets the negative-zero
case wrong relative to the documented three-valued definition; an implementation written with
two comparisons gets it right. Since the difference shows up on exactly one input class, it
survives casual testing indefinitely. This is the reason the negative-zero probe below is worth
running even though the case looks exotic.
What a careful implementation does: two comparisons against literal zero, in the order
x > 0, then x < 0, then 0. Under IEEE comparison semantics this handles both zeros
correctly and needs no special case. It is three lines and there is no cleverer version worth
having.
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.
SIGN · 1 lines · calc-func/src/catalogue/rounding.rs on GitHubcall(SIGN, "SIGN", 1, NUMBER, sign)
sign · 15 lines · calc-func/src/catalogue/rounding.rs on GitHub/// SIGN: 1 for a positive number, -1 for a negative one, 0 for zero.
fn sign(
arguments: &[CalcValue],
services: &mut EvalServices<'_>,
) -> Result<CalcValue, FunctionFault> {
numeric(SIGN, arguments, services, |_, n| {
Ok(if n[0] > 0.0 {
1.0
} else if n[0] < 0.0 {
-1.0
} else {
0.0
})
})
}
out_with_subnormal catalogue/kitNo implementation has been published with a Handbook test suite for this function.
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 build | Platform and CPU | Captured inputs |
|---|---|---|
| 19929 | Windows, bitness not recorded, CPU not recorded | 40 |
| 20430 | Windows, 64-bit, CPU not recorded | 1,226 |
Agreement on these compared inputs does not establish agreement on unmeasured inputs.
Recorded environments and comparison details.
Windows, bitness not recorded, CPU not recorded
40 captured inputs are indexed for this environment. Capture dates are not recorded. This is a reading count, not a comparison with another build.
Windows, 64-bit, CPU not recorded
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.
ABS — the other half of the decomposition x = SIGN(x) * ABS(x). The two are almost
always used together.IF(x>0, 1, IF(x<0, -1, 0)) — the hand-written equivalent, and worth mentioning because
it is the form readers write when they have forgotten SIGN exists. It also makes the
comparison semantics explicit, which SIGN hides.GESTEP and DELTA (engineering category) — the other threshold functions. DELTA(a, b)
is an equality indicator and GESTEP(x, step) a step function; between them and SIGN there
are three different conventions for what happens exactly at the boundary, and they do not
agree with each other.TANH — the smooth saturating analogue. Where SIGN is used to steer a computation,
TANH(k*x) for large k is the differentiable stand-in, which is why it turns up in
optimization work.TRUNC, INT, ROUND — the rounding family shares SIGN's sensitivity to which side of
zero a value falls on; TRUNC in particular is "round toward zero", i.e. rounding in the
direction opposite to SIGN.ABS (magnitude, not direction) and with a two-valued sign, which is what
most programming languages' bit-level helpers return.No named variants are recorded yet.
Suggest a correction or contribute an implementation · For agents