Numbers¶
Format decimals, percentages, units, scientific and compact notation, and spelled-out or ordinal forms — all in the locale's conventions, straight from ICU. For currency amounts, see Money & currency.
Every numeric method shapes its output for the instance locale: the grouping and
decimal separators, the digit set (Western 0-9, Arabic-Indic ٠-٩, Devanagari
०-९, …), and the sign and percent placement all come from CLDR. You never
format digits by hand — that is the whole point. The job of this page is to show
you which method to reach for, and exactly which knobs each one exposes.
Method overview¶
| Method | Use it for | Returns |
|---|---|---|
number(value, options?) |
A plain decimal in the locale's style | "123.400,5" |
precision(value, fractionDigits?, options?) |
A decimal with a fixed number of fraction digits (default 2) | "1.00" |
percentage(value, precision?, options?) |
A fraction rendered as a percent | "20%" |
unit(category, unit, value, width?) |
A measurement with its localised unit | "2.19 gigabytes" |
compact(value, width?) |
A short magnitude for large numbers | "1.2K" / "1.2 thousand" |
scientific(value) |
Exponential notation | "1.2345E4" |
spellout(value) |
A number written out in words | "one hundred twenty" |
ordinal(value) |
Ordinal text | "2nd" |
symbol(name) |
A single locale notation symbol | "٫" (Persian decimal mark) |
All of number(), precision(), percentage(), and money() accept
the same options bag; the rest take simple positional
arguments described inline.
Decimals, percentages & units¶
number() formats a plain decimal in the locale's style — note how de swaps
the roles of . and ,. Pass the options bag to
control rounding, fraction digits, and grouping.
precision() is the shortcut for a fixed number of fraction digits: it
always renders exactly fractionDigits places (default 2), padding with trailing
zeros and rounding as needed. precision(1) → "1.00" and precision(1.002) →
"1.00" — never "1.0". It is the ergonomic form of
number(value, { minimumFractionDigits: n, maximumFractionDigits: n }), and like
the others it stays fully localised (de → "1,00"). Pass the
options bag as a trailing argument to widen the band
(e.g. { maximumFractionDigits: 3 }) or change the rounding mode.
percentage() takes a fraction, not a pre-multiplied percent: 0.2 →
20%. The optional second argument is the maximum fraction digits (default 3),
so percentage(0.1234, 1) → "12.3%". Anything you can pass number() you can
also pass as a third options argument; an explicit maximumFractionDigits there
overrides the precision shortcut.
unit() pairs a measurement type and unit with a value and an optional
width. The type/unit names are the CLDR identifiers
(digital/gigabyte, temperature/celsius, length/meter, …). The width
selects verbosity:
width |
Example (celsius, 26) |
Notes |
|---|---|---|
none / long / full |
26 degrees Celsius |
Spelled-out unit name (the default is full/long) |
medium |
26°C |
"short" ICU display |
short |
26°C |
"narrow" ICU display — tightest |
Finding valid unit identifiers
unit() accepts the ECMA-402 sanctioned units only. List the ones your runtime
supports with supportedValues("unit") and pass them as
the unit argument. The category argument ("digital", "temperature", …)
is descriptive grouping — ICU does not require it to match, but keeping it
accurate documents intent.
Number-formatting options¶
number(), precision(), percentage(), and money() accept an
options bag — the same keys in every port, even camelCase in Python, so one JSON config travels
between languages unchanged (see Terminology).
Java passes a Map<String, Object> with the same camelCase keys. C# uses a
NumberOptions object initializer with PascalCase property names (e.g. MaximumFractionDigits).
The default rounding mode is halfExpand (round half away from zero — the everyday
"round 0.5 up" rule) in all five ports.
| Key | Type / values | What it does |
|---|---|---|
minimumIntegerDigits |
int | Zero-pads the whole part (5 → "005" at 3). |
minimumFractionDigits |
int | Pads the fraction with trailing zeros up to N places. |
maximumFractionDigits |
int | Rounds the fraction to at most N places. |
minimumSignificantDigits |
int | Keep at least N significant digits. |
maximumSignificantDigits |
int | Round to at most N significant digits. |
roundingMode |
ceil · floor · expand · trunc · halfExpand · halfTrunc · halfEven |
How the last kept digit is rounded. Portable across all ports. |
roundingIncrement |
1,2,5,10,20,25,50,100,…,5000 |
Round to a multiple (e.g. 25 → nearest 0.25 with 2 fraction digits — "nickel rounding"). |
useGrouping |
always · auto · min2 · true/false |
Thousands separators. PHP/Python coerce any truthy value to "on"; JS honours the full set. |
Significant vs fraction digits
ICU treats significant-digit limits and fraction-digit limits as mutually exclusive. Set one or the other, not both — significant digits win where both are supplied.
The following keys are JavaScript-only. The PHP and Python ports use a legacy
ICU formatter that has no equivalent attribute, so they accept the keys silently
but ignore them. Use the dedicated compact() /
scientific() methods for those notations in
every port.
| Key (JS only) | Values | What it does |
|---|---|---|
signDisplay |
auto · always · exceptZero · negative · never |
When to show the sign. |
trailingZeroDisplay |
auto · stripIfInteger |
Drop .00 on whole values. |
roundingPriority |
auto · morePrecision · lessPrecision |
Resolve fraction vs significant conflicts. |
notation |
standard · scientific · engineering · compact |
Inline notation switch. |
compactDisplay |
short · long |
Only with notation: "compact". |
Options in practice¶
const c = new Cosmo("en");
c.number(1234.5, { minimumFractionDigits: 2 }); // "1,234.50"
c.number(1234.567, { maximumFractionDigits: 2 }); // "1,234.57"
c.number(2.005, { maximumFractionDigits: 2,
roundingMode: "halfEven" }); // "2" (banker's)
c.number(1234.5, { useGrouping: false }); // "1234.5"
c.percentage(0.1234, 1); // "12.3%"
$c = new Cosmo('en');
$c->number(1234.5, ['minimumFractionDigits' => 2]); // "1,234.50"
$c->number(1234.567, ['maximumFractionDigits' => 2]); // "1,234.57"
$c->number(2.005, ['maximumFractionDigits' => 2,
'roundingMode' => 'halfEven']); // "2"
$c->number(1234.5, ['useGrouping' => false]); // "1234.5"
$c->percentage(0.1234, 1); // "12.3%"
c = Cosmo("en")
c.number(1234.5, {"minimumFractionDigits": 2}) # "1,234.50"
c.number(1234.567, {"maximumFractionDigits": 2}) # "1,234.57"
c.number(2.005, {"maximumFractionDigits": 2,
"roundingMode": "halfEven"}) # "2"
c.number(1234.5, {"useGrouping": False}) # "1234.5"
c.percentage(0.1234, 1) # "12.3%"
Cosmo c = new Cosmo("en");
c.number(1234.5, Map.of("minimumFractionDigits", 2)); // "1,234.50"
c.number(1234.567, Map.of("maximumFractionDigits", 2)); // "1,234.57"
c.number(2.005, Map.of("maximumFractionDigits", 2,
"roundingMode", "halfEven")); // "2"
c.number(1234.5, Map.of("useGrouping", false)); // "1234.5"
c.percentage(0.1234, 1); // "12.3%"
var c = new Cosmo("en");
c.Number(1234.5, new NumberOptions { MinimumFractionDigits = 2 }); // "1,234.50"
c.Number(1234.567, new NumberOptions { MaximumFractionDigits = 2 }); // "1,234.57"
c.Number(2.005, new NumberOptions { MaximumFractionDigits = 2,
RoundingMode = "halfEven" }); // "2"
c.Number(1234.5, new NumberOptions { UseGrouping = false }); // "1234.5"
c.Percentage(0.1234, 1); // "12.3%"
Compact & scientific notation¶
compact() shortens large magnitudes for dashboards, social counters, and tight
columns. The width chooses between the symbol form (short, the default —
1.2K) and the spelled scale word (long/full — 1.2 thousand), both
fully localised (German 1,2 Tsd., Japanese 1.2万). scientific() renders
exponential notation at full double precision.
compact() and scientific() work everywhere
Both are available in all five ports. PHP reaches compact notation through
an ICU compact-notation style its ext-intl binding accepts even though it
isn't a named constant; the others use the modern ICU NumberFormatter.
Spelled-out & ordinal numbers¶
spellout() writes a number out in words (cheques, accessibility, voice UIs);
ordinal() gives the ordinal text (1st, 2nd, 3rd, localised). symbol()
returns a single locale notation symbol by name (decimal, group, percent,
minusSign, plusSign, nan, infinity, currency) — useful when you compose a
number inside a custom template and need just the separator.
spellout() / ordinal() are PHP, Python, Java & C#
Spelling numbers out and ordinal text ("1st", "2nd") come from ICU's
rule-based number formatter (RBNF), which the JavaScript Intl API does not
expose — so these four tabs omit JS. For the ordinal plural category (which
JS does have, e.g. to pick "1st" vs "2nd" wording yourself), see
Messages & plurals. symbol() likewise accepts a wider
set of names in PHP/Python/Java/C# than the JS Intl-exposed set.
Practical examples¶
A file-size display. Pick the unit by magnitude, then format with the
digital category at a tight width:
A percentage with a guaranteed decimal. Combine the precision shortcut with
an options bag to also pin a minimum:
"Nickel rounding" with roundingIncrement. Round a price to the nearest 0.05: