Operators
Percentage (%)
Implemented; no recorded answers are attributed to this entry
No local names are recorded for this entry.
What it does
number%
A% converts its operand to a number and returns that number scaled by one hundredth. 50%
is 0.5; A1% is a hundredth of whatever A1 holds.
The interesting content is in the word "scaled", because binary64 gives two inequivalent spellings of it:
x / 100— divide by an exactly representable integer, one rounding.x * 0.01— multiply by the double nearest to one hundredth, which is not one hundredth, and then round.
These do not agree for every x. The literal 0.01 is already a rounded approximation, so
the multiplication rounds twice in effect; the division rounds once against an exact divisor
and is the more accurate of the two. For most operands both spellings land on the same
double, and for some they do not — which makes this a real, if small, last-bit question about
a function whose definition looks trivial.
The percent format is a separate thing entirely. Formatting a cell as a percentage changes
how a number is displayed and how typed input is interpreted by the host; % as an operator
changes the value. A cell holding 0.5 formatted as a percentage shows 50% without this
operator ever running. Chapter 01's rule applies: dates, currency and percentages are numbers
wearing formats.
Arguments
| Position | Name | Meaning |
|---|---|---|
| 0 | A | The operand to scale. Required. |
Arity is exactly 1; no optional arguments, no defaults. The operator is postfix — it follows its operand — which makes it the only member of the arithmetic family with that shape.
Postfix position raises a precedence question (-2%, 2^3%, 2%%) that this Handbook does
not answer: formula grammar and precedence are explicitly out of scope (CHARTER.md section
4), and the operator-inventory decision register in the sources records precedence ownership
as an open item. What the Handbook can say is that % is a one-argument function of a
value, and that chaining it (A%%) applies it twice.
Try it
Quirks
Result and edge cases
- Text and logical operands. Shared to-number rules from
coercion and lifting. Note the overlap: chapter 02
records that Excel's text-to-number recognizer itself accepts percent signs in some
locale-dependent forms, so
"50%"as text may already convert to0.5before this operator is reached — and"50%"%would then scale it again. That interaction is unrecorded here and is a good probe. - Empty and omitted. Per-family policy under chapter 02; unrecorded for this row.
- Arrays.
CoercionLiftProfile::UnaryNumericScalarOrArrayElementwise— mapped elementwise, with element-local failures. - Underflow. Scaling a subnormal by a hundredth flushes it toward zero; scaling any tiny
value repeatedly reaches zero. Nothing about this is specific to
%, but%is a cheap way to reach the subnormal range from ordinary-looking data. - Overflow. Not reachable: scaling down cannot overflow.
How to implement
Notes for implementers
- Pick a spelling and record which one:
x / 100orx * 0.01. They are not the same function of a double, and a compatibility implementation that guesses will disagree with Excel on some operands. The Handbook cannot yet tell you which to pick. - Do not implement
%by string manipulation of the formula or by adjusting the cell format. It is a value transformation. - Chained application (
A%%) must scale twice; there is no idempotence to exploit. - The elementwise array path must preserve element-local failures.
Rust code
Show the CalcFunc source of this function
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.
% postfix · 1 lines · calc-func/src/catalogue/arithmetic.rs on GitHubCatalogueEntry::operator(PERCENT, "%", Notation::Postfix, NUMBER, percent)
percent · 13 lines · calc-func/src/catalogue/arithmetic.rs on GitHub/// `x%` is `x / 100`.
fn percent(
arguments: &[CalcValue],
services: &mut EvalServices<'_>,
) -> Result<CalcValue, FunctionFault> {
let site = Site::new(PERCENT, services);
Site::finish(
site.scalar_operands(arguments)
.and_then(|()| site.number_argument(0, &arguments[0]))
.and_then(|x| site.divide(x, 100.0))
.and_then(|x| site.number(x)),
)
}
Kernels shared with other functions
dividecatalogue/arithmeticflushedcatalogue/arithmeticbinarycatalogue/arithmeticoperandscatalogue/arithmetic
Argument and result plumbing
CatalogueEntry::operatorcatalogue
No implementation has been published with a Handbook test suite for this function.
Version differences
No comparison between specific Excel builds is recorded here yet. This does not establish that all builds behave alike.
Alternatives
Relationships
FUNC.OP_DIVIDEandFUNC.OP_MULTIPLY— the two operators%might be implemented in terms of, and the reason the ambiguity above matters.FUNC.OP_NEGATE,FUNC.OP_UNARY_PLUS— the other unary members of the family.PERCENTILE,PERCENTRANK,PERCENTOF— statistical functions whose names share the word and share nothing else.TEXT(x, "0%")— the formatting route. If the goal is display,%-the-operator is the wrong tool; if the goal is arithmetic, the format is.
Named variants
No named variants are recorded yet.
Suggest a correction or contribute an implementation · For agents