• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1---
2layout: default
3title: Number Skeletons
4nav_order: 3
5grand_parent: Formatting
6parent: Formatting Numbers
7---
8<!--
9© 2019 and later: Unicode, Inc. and others.
10License & terms of use: http://www.unicode.org/copyright.html
11-->
12
13# Number Skeletons
14{: .no_toc }
15
16## Contents
17{: .no_toc .text-delta }
18
191. TOC
20{:toc}
21
22---
23
24## Overview
25
26Number skeletons are a locale-agnostic way to configure a `NumberFormatter` in
27ICU. Number skeletons work in `MessageFormat`.
28
29Number skeletons consist of case-sensitive tokens that correspond to settings
30in ICU `NumberFormatter`. For example, to format a currency in compact notation
31with the sign always shown, you could use this skeleton:
32
33    sign-always compact-short currency/GBP
34
35***Since ICU 67***, you can also use more concise syntax:
36
37    +! K currency/GBP
38
39To use a skeleton in `MessageFormat`, use the "number" type and prefix the
40skeleton with `::`
41
42    {0, number, :: +! K currency/GBP}
43
44The ICU `toSkeleton()` API outputs the long-form skeletons, but all parts of
45ICU that read user-specified number skeletons accept both long-form and
46concise skeletons.
47
48## Syntax
49
50A token consists of a *stem* and zero or more *options*.  The stem is what
51occurs before the first `"/"` character in a token, and the options are each of
52the subsequent `"/"`-delimited strings.  For example, `"compact-short"` and
53"currency" are stems, and `"GBP"` is an option.
54
55Tokens are space-separated, with exceptions for concise skeletons listed at
56the end of this document.
57
58Stems might also be dynamic strings (not a fixed list); these are called
59*blueprint stems*.  For example, to format a number with 2-3 significant
60digits, you could use the following stem:
61
62    @@#
63
64A few examples of number skeletons are shown below. The list of available
65stems and options can be found below in [Skeleton Stems and
66Options](#skeleton-stems-and-options).
67
68## Examples
69
70| Long Skeleton | Concise Skeleton | Input | en-US Output | Comments |
71|---|---|---|---|---|
72| `percent` | `%` | 25 | 25% |
73| `.00` | `.00` | 25 | 25.00 | Equivalent to `Precision::fixedFraction(2)` |
74| `percent .00` | `% .00` | 25 | 25.00% |
75| `scale/100` | `scale/100` | 0.3 | 30 | Multiply by 100 before formatting |
76| `percent scale/100` | `%x100` | 0.3 | 30% |
77| `measure-unit/length-meter` | `unit/meter` | 5 | 5 m | `UnitWidth` defaults to `Short` |
78| `measure-unit/length-meter` <br/> `unit-width-full-name` | `unit/meter` <br/> `unit-width-full-name` | 5 | 5 meters |
79| `currency/CAD` | `currency/CAD` | 10 | CA$10.00 |
80| `currency/CAD` <br/> `unit-width-narrow` | `currency/CAD` <br/> `unit-width-narrow` | 10 | $10.00 | Use the narrow symbol variant |
81| `compact-short` | `K` | 5000 | 5K |
82| `compact-long` | `KK` | 5000 | 5 thousand |
83| `compact-short` <br/> `currency/CAD` | `K currency/CAD` | 5000 | CA$5K |
84| - | - | 5000 | 5,000 |
85| `group-min2` | `,?` | 5000 | 5000 | Require 2 digits in group for separator |
86| `group-min2` | `,?` | 15000 | 15,000 |
87| `sign-always` | `+!` | 60 | +60 | Show sign on all numbers |
88| `sign-always` | `+!` | 0 | +0 |
89| `sign-except-zero` | `+?` | 60 | +60 | Show sign on all numbers except 0 |
90| `sign-except-zero` | `+?` | 0 | 0 |
91| `sign-accounting` <br/> `currency/CAD` | `() currency/CAD` | -40 | (CA$40.00) |
92
93## Skeleton Stems and Options
94
95The full set of features supported by number skeletons is listed by category below.
96
97### Notation
98
99Use one of the following stems to select compact or simple notation:
100
101- `compact-short` or `K` (concise)
102- `compact-long` or `KK` (concise)
103- `notation-simple` (or omit since this is default)
104
105There are two ways to select scientific or engineering notation: using long-form syntax or concise syntax.
106
107#### Scientific and Engineering Notation: Long Form
108
109Start with the stem `scientific` or `engineering`.  Those stems take the following optional options:
110
111- `/sign-xxx` sets the sign display option for the exponent; see [Sign](#sign).
112- `/*ee` sets exponent digits to "at least 2"; use `/*eee` for at least 3 digits, etc.
113    - ***Prior to ICU 67***, use `/+ee` instead of `/*ee`.
114
115For example, all the following skeletons are valid:
116
117- `scientific`
118- `scientific/sign-always`
119- `scientific/*ee`
120- `scientific/*ee/sign-always`
121
122#### Scientific and Engineering Notation: Concise Form
123
124The following are examples of concise form:
125
126| Concise Skeleton | Equivalent Long-Form Skeleton |
127|---|---|
128| `E0` | `scientific` |
129| `E00` | `scientific/*ee` |
130| `EE+!0` | `engineering/sign-always` |
131| `E+?00` | `scientific/sign-except-zero/+ee` |
132
133More precisely:
134
1351. Start with `E` for scientific or `EE` for engineering.
1362. Allow either `+!` or `+?` as a concise sign display option.
1373. Expect one or more `0`s.  If more than one, set minimum integer digits.
138
139### Unit
140
141The supported types of units are percent, currency, and measurement units.
142The following skeleton tokens are accepted:
143
144- `percent` or `%` (concise)
145- Special: `%x100` to scale the number by 100 and then format with percent
146- `permille`
147- `base-unit`
148- `currency/XXX`
149- `measure-unit/aaaa-bbbb` or `unit/bbb` (concise)
150
151The `percent`, `permille`, and `base-unit` stems do not take any options.
152
153The `currency` stem takes one required option: the three-letter ISO code of
154the currency to be formatted.
155
156The `measure-unit` stem takes one required option: the unit identifier of the
157unit to be formatted.  The full unit identifier is required: both the type and
158the subtype (for example, `length-meter`).
159
160The `unit` stem is an alternative to `measure-unit` that accepts a core unit
161identifier with the subtype but not the type (for example, `meter` instead of
162`length-meter`).  It also supports variations allowed by UTS 35, including the per unit with the `-per-` infix (for example, `unit/furlong-per-second`).
163
164### Per Unit
165
166To specify a unit to put in the denominator, use the following skeleton token.
167As with the `measure-unit` stem, pass the unit identifier as the option:
168
169- `per-measure-unit/aaaa-bbbb`
170
171Note that if the `unit` stem is used, the denominator can be placed in the same
172token as the numerator.
173
174### Unit Width
175
176The unit width can be specified by the following stems:
177
178- `unit-width-narrow`
179- `unit-width-short`
180- `unit-width-full-name`
181- `unit-width-iso-code`
182- `unit-width-hidden`
183
184For more details, see
185[`UNumberUnitWidth`](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/unumberformatter_8h.html).
186
187### Precision
188
189The precision category has more blueprint stems than most other categories;
190they are documented in detail below. The following non-blueprint stems are
191accepted:
192
193- `precision-integer` (round to the nearest integer) --- accepts fraction-precision options
194- `precision-unlimited` (do not perform rounding; display all digits)
195- `precision-increment/dddd` (round to *`dddd`*, a decimal number) --- see below
196- `precision-currency-standard`
197- `precision-currency-cash`
198
199To round to the nearest nickel, for example, use the skeleton
200`precision-increment/0.05`.  For more information on the decimal number
201syntax, see [Scale](#scale).
202
203#### Fraction Precision
204
205The following are examples of fraction-precision stems:
206
207| Stem | Explanation | Equivalent C++ Code |
208|---|---|---|
209| `.00` | Exactly 2 fraction digits | `Precision::fixedFraction(2) ` |
210| `.00*` | At least 2 fraction digits | `Precision::minFraction(2)` |
211| `.##` | At most 2 fraction digits | `Precision::maxFraction(2) ` |
212| `.0#` | Between 1 and 2 fraction digits | `Precision::minMaxFraction(1, 2)` |
213
214More precisely, the fraction precision stem starts with `.`, then contains
215zero or more `0` symbols, which implies the minimum fraction digits.  Then it
216contains either a `*`, for unlimited maximum fraction digits, or zero or more
217`#` symbols, which implies the minimum fraction digits when added to the `0`
218symbols.
219
220Note that the stem `.` is considered valid and is equivalent to `precision-integer`.
221
222Fraction-precision stems accept a single optional option: a number of significant digits.
223The options here correspond to the API functions on `FractionPrecision`. Some options
224require specifying `r` or `s` for relaxed mode or strict mode. For more information, see
225the API docs for UNumberRoundingPriority.
226
227| Skeleton | Explanation | Equivalent C++ Code |
228|---|---|---|
229| `.##/@@@*` | At most 2 fraction digits, but guarantee <br/> at least 3 significant digits | `Precision::maxFraction(2)` <br/> `.withMinDigits(3)` |
230| `.##/@##r` | Same as above | `Precision::maxFraction(2)` <br/> `.withSignificantDigits(1, 3, RELAXED)` |
231| `.##/@@@r` | Same as above, but pad trailing zeros <br/> to at least 3 significant digits | `Precision::maxFraction(2)` <br/> `.withSignificantDigits(3, 3, RELAXED)` |
232| `.00/@##` | Exactly 2 fraction digits, but do not <br/> display more than 3 significant digits | `Precision::fixedFraction(2)` <br/> `.withMaxDigits(3)` |
233| `.00/@##s` | Same as above | `Precision::fixedFraction(2)` <br/> `.withSignificantDigits(1, 3, STRICT)` |
234| `.00/@@@s` | Same as above, but pad trailing zeros <br/> to at least 3 significant digits | `Precision::fixedFraction(2)` <br/> `.withSignificantDigits(3, 3, STRICT)` |
235
236Precisely, the option follows the syntax of the significant digits stem (see below),
237but one of the following must be true:
238
239- Option has one or more `@`s followed by the wildcard character (`withMinDigits`)
240- Option has exactly one `@` followed by zero or more `#`s (`withMaxDigits`)
241- Option has one or more `@`s followed by zero or more `#`s and ends in `s` or `r` (`withSignificantDigits`)
242
243#### Significant Digits Precision
244
245The following are examples of stems for significant figures:
246
247| Stem | Explanation | Equivalent C++ Code|
248|---|---|---|
249| `@@@` | Exactly 3 significant digits | `Precision::fixedSignificantDigits(3)` |
250| `@@@*` | At least 3 significant digits | `Precision::minSignificantDigits(3)` |
251| `@##` | At most 3 significant digits | `Precision::maxSignificantDigits(3)` |
252| `@@#` | Between 2 and 3 significant digits | `...::minMaxSignificantDigits(2, 3)` |
253
254The precise syntax is very similar to fraction precision.  The blueprint stem
255starts with one or more `@` symbols, which implies the minimum significant
256digits.  Then it contains either a `*`, for unlimited maximum significant
257digits, or zero or more `#` symbols, which implies the minimum significant
258digits when added to the `@` symbols.
259
260#### Trailing Zero Display
261
262***Starting with ICU 69***, a new option called `trailingZeroDisplay` was added.
263To enable this in an ICU number skeleton, append `/w` to any precision token:
264
265| Skeleton | Explanation | Equivalent C++ Code |
266|---|---|---|
267| `.00/w` | Exactly 2 fraction digits, but hide <br/> them if they are all 0 | `Precision::fixedFraction(2)` <br/> `.trailingZeroDisplay(` <br/> `UNUM_TRAILING_ZERO_HIDE_IF_WHOLE)` |
268| `precision-curren` <br/> `cy-standard/w` | Currency rounding, but hide <br/> fraction digits if they are all 0 | `Precision::currency(UCURR_USAGE_STANDARD)` <br/> `.trailingZeroDisplay(` <br/> `UNUM_TRAILING_ZERO_HIDE_IF_WHOLE)` |
269
270#### Wildcard Character
271
272***Prior to ICU 67***, the symbol `+` was used for unlimited precision, instead
273of `*` (for example, `.00+`). For backwards compatibility, either `+` or `*` is
274accepted. This applies for both fraction digits and significant digits.
275
276### Rounding Mode
277
278The rounding mode can be specified by the following stems:
279
280- `rounding-mode-ceiling`
281- `rounding-mode-floor`
282- `rounding-mode-down`
283- `rounding-mode-up`
284- `rounding-mode-half-even`
285- `rounding-mode-half-down`
286- `rounding-mode-half-up`
287- `rounding-mode-unnecessary`
288
289For more details, see [Rounding Modes](rounding-modes.md).
290
291### Integer Width
292
293The following examples show how to specify integer width (minimum or maximum
294integer digits):
295
296| Long Form | Concise Form | Explanation | Equivalent C++ Code |
297|---|---|---|---|
298| `integer-width/*000` | `000` | At least 3 <br/> integer digits | `IntegerWidth::zeroFillTo(3)` |
299| `integer-width/##0` | - | Between 1 and 3 <br/> integer digits | `IntegerWidth::zeroFillTo(1)` <br/> `.truncateAt(3)`
300| `integer-width/00` | - | Exactly 2 <br/> integer digits | `IntegerWidth::zeroFillTo(2)` <br/> `.truncateAt(2)` |
301| `integer-width/*` | - | Zero or more <br/> integer digits | `IntegerWidth::zeroFillTo(0) `
302| `integer-width-trunc` | - | Zero integer digits | `IntegerWidth::zeroFillTo(0)` <br/> `.truncateAt(0)`
303
304The long-form option starts with either a single `*` symbol, signaling no limit
305on the number of integer digits (no *`truncateAt`*), or zero or more `#` symbols.
306It should then be followed by zero or more `0` symbols, indicating the minimum
307integer digits (the argument to *`zeroFillTo`*).  If there is no `*` symbol, the
308maximum integer digits (the argument to *`truncateAt`*) is the number of `#`
309symbols plus the number of `0` symbols.
310
311The concise skeleton is simply one or more `0` characters. This supports
312minimum integer digits but not maximum integer digits.
313
314The special stem `integer-width-trunc` covers the case when both *`truncateAt`* and *`zeroFillTo`* are zero.
315
316***Prior to ICU 67***, use the symbol `+` instead of `*`.
317
318### Scale
319
320To specify the scale, use the following stem and option:
321
322- `scale/dddd`
323
324where *`dddd`* is a decimal number. For example, the following are valid skeletons:
325
326- `scale/100` (multiply by 100)
327- `scale/1E2` (same as above)
328- `scale/0.5` (multiply by 0.5)
329
330The decimal number should conform to a standard decimal number syntax. In
331C++, it is parsed using the decimal number library described in
332[LocalizedNumberFormatter::formatDecimal](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1number_1_1LocalizedNumberFormatter.html).
333In Java, it is parsed using
334[BigDecimal](https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#BigDecimal%28java.lang.String%29).
335For maximum compatibility, it is highly recommended that your decimal number
336is able to be parsed by both engines.
337
338### Grouping
339
340The grouping strategy can be specified by the following stems:
341
342- `group-off` or `,_` (concise)
343- `group-min2` or `,?` (concise)
344- `group-auto` (or omit since this is the default)
345- `group-on-aligned` or `,!` (concise)
346- `group-thousands` (no concise equivalent)
347
348For more details, see
349[`UNumberGroupingStrategy`](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/unumberformatter_8h.html).
350
351### Symbols
352
353The following stems are allowed for specifying the number symbols:
354
355- `latin` (use Latin-script digits)
356- `numbering-system/nnnn` (use the `nnnn` numbering system)
357
358A custom `NDecimalFormatSymbols` instance is not supported at this time.
359
360### Sign Display
361
362The following stems specify sign display:
363
364- `sign-auto` (or omit since this is the default)
365- `sign-always` or `+!` (concise)
366- `sign-never` or `+_` (concise)
367- `sign-accounting` or `()` (concise)
368- `sign-accounting-always` or `()!` (concise)
369- `sign-except-zero` or `+?` (concise)
370- `sign-accounting-except-zero` or `()?` (concise)
371- `sign-negative` or `+-` (concise)
372- `sign-accounting-negative` or `()-` (concise)
373
374For more details, see
375[`UNumberSignDisplay`](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/unumberformatter_8h.html).
376
377### Decimal Separator Display
378
379The following stems specify decimal separator display:
380
381- `decimal-auto`
382- `decimal-always`
383
384For more details, see
385[`UNumberDecimalSeparatorDisplay`](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/unumberformatter_8h.html).
386