The NumberFormat constructor is the %NumberFormat% intrinsic object and a standard built-in property of the Intl object. Behaviour common to all service constructor properties of the Intl object is specified in .
The abstract operation InitializeNumberFormat accepts the arguments numberFormat (which must be an object), locales, and options. It initializes numberFormat as a NumberFormat object. The following steps are taken:
The abstract operation SetNumberFormatDigitOptions applies digit
options used for number formatting onto the intl object.
It is used by both Intl.NumberFormat and Intl.PluralRules.
Let mnid be ? GetNumberOption(options, "minimumIntegerDigits,", 1, 21, 1).
Let mnfd be ? Get(options, "minimumFractionDigits").
Let mxfd be ? Get(options, "maximumFractionDigits").
Let mnsd be ? Get(options, "minimumSignificantDigits").
Let mxsd be ? Get(options, "maximumSignificantDigits").
Set intlObj.[[MinimumIntegerDigits]] to mnid.
Let roundingPriority be ? GetOption(options, "roundingPriority", string, « "auto", "morePrecision", "lessPrecision" », "auto").
Let roundingIncrement be ? GetNumberOption(options, "roundingIncrement", 1, 5000, 1).
If roundingIncrement is not in « 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000 », throw a RangeError exception.
Let roundingMode be ? GetOption(options, "roundingMode", string, « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », "halfExpand").
Let trailingZeroDisplay be ? GetOption(options, "trailingZeroDisplay", string, « "auto", "stripIfInteger" », "auto").
NOTE: All fields required by SetNumberFormatDigitOptions have now been read from options. The remainder of this AO interprets the options and may throw exceptions.
If roundingIncrement is not 1, set mxfdDefault to mnfdDefault.
Set intlObj.[[RoundingIncrement]] to roundingIncrement.
Set intlObj.[[RoundingMode]] to roundingMode.
Set intlObj.[[TrailingZeroDisplay]] to trailingZeroDisplay.
If mnsd is not undefined or mxsd is not undefined, then
Let hasSd be true.
Else,
Let hasSd be false.
If mnfd is not undefined or mxfd is not undefined, then
Let hasFd be true.
Else,
Let hasFd be false.
Let needSd be true.
Let needFd be true.
If roundingPriority is "auto", then
Set needSd to hasSd.
If hasSd is true, or hasFd is false and notation is "compact", then
Set needFd to false.
If needSd is true, then
If hasSd is true, then
Set mnsd to ? DefaultNumberOption(mnsd, 1, 21, 1).
Set mxsd to ? DefaultNumberOption(mxsd, mnsd, 21, 21).
Set intlObj.[[MinimumSignificantDigits]] to mnsd.
Set intlObj.[[MaximumSignificantDigits]] to mxsd.
Else,
Set intlObj.[[MinimumSignificantDigits]] to 1.
Set intlObj.[[MaximumSignificantDigits]] to 21.
If needFd is true, then
If hasFd is true, then
Set mnfd to ? DefaultNumberOption(mnfd, 0, 20, undefined).
Set mxfd to ? DefaultNumberOption(mxfd, 0, 20, undefined).
If mnfd is undefined, set mnfd to min(mnfdDefault, mxfd).
Else if mxfd is undefined, set mxfd to max(mxfdDefault, mnfd).
Else if mnfd is greater than mxfd, throw a RangeError exception.
Set intlObj.[[MinimumFractionDigits]] to mnfd.
Set intlObj.[[MaximumFractionDigits]] to mxfd.
Else,
Set intlObj.[[MinimumFractionDigits]] to mnfdDefault.
Set intlObj.[[MaximumFractionDigits]] to mxfdDefault.
If needSd is true or needFd is true, then
If roundingPriority is "morePrecision", then
Set intlObj.[[RoundingType]] to morePrecision.
Else if roundingPriority is "lessPrecision", then
Set intlObj.[[RoundingType]] to lessPrecision.
Else if hasSd is true, then
Set intlObj.[[RoundingType]] to significantDigits.
Else,
Set intlObj.[[RoundingType]] to fractionDigits.
Else,
Set intlObj.[[RoundingType]] to morePrecision.
Set intlObj.[[MinimumFractionDigits]] to 0.
Set intlObj.[[MaximumFractionDigits]] to 0.
Set intlObj.[[MinimumSignificantDigits]] to 1.
Set intlObj.[[MaximumSignificantDigits]] to 2.
If roundingIncrement is not 1, then
If intlObj.[[RoundingType]] is not fractionDigits, throw a TypeError exception.
If intlObj.[[MaximumFractionDigits]] is not equal to intlObj.[[MinimumFractionDigits]], throw a RangeError exception.
The value of the [[AvailableLocales]] internal slot is implementation-defined within the constraints described in .
The value of the [[RelevantExtensionKeys]] internal slot is « "nu" ».
Note 1
Unicode Technical Standard #35 describes three locale extension keys that are relevant to number formatting: "cu" for currency, "cf" for currency format style, and "nu" for numbering system. Intl.NumberFormat, however, requires that the currency of a currency format is specified through the currency property in the options objects, and the currency format style of a currency format is specified through the currencySign property in the options objects.
The value of the [[LocaleData]] internal slot is implementation-defined within the constraints described in and the following additional constraints:
The list that is the value of the "nu" field of any locale field of [[LocaleData]] must not include the values "native", "traditio", or "finance".
[[LocaleData]].[[<locale>]] must have a [[patterns]] field for all locale values locale. The value of this field must be a Record, which must have fields with the names of the four number format styles: "decimal", "percent", "currency", and "unit".
The two fields "currency" and "unit" noted above must be Records with at least one field, "fallback".
The "currency" may have additional fields with keys corresponding to currency codes according to .
Each field of "currency" must be a Record with fields corresponding to the possible currencyDisplay values: "code", "symbol", "narrowSymbol", and "name".
Each of those fields must contain a Record with fields corresponding to the possible currencySign values: "standard" or "accounting". The "unit" field (of [[LocaleData]].[[<locale>]]) may have additional fields beyond the required field "fallback" with keys corresponding to core measurement unit identifiers corresponding to .
Each field of "unit" must be a Record with fields corresponding to the possible unitDisplay values: "narrow", "short", and "long".
All of the leaf fields so far described for the patterns tree ("decimal", "percent", great-grandchildren of "currency", and grandchildren of "unit") must be Records with the keys "positivePattern", "zeroPattern", and "negativePattern".
The value of the aforementioned fields (the sign-dependent pattern fields) must be string values that must contain the substring "{number}".
"positivePattern" must contain the substring "{plusSign}" but not "{minusSign}"; "negativePattern" must contain the substring "{minusSign}" but not "{plusSign}"; and "zeroPattern" must not contain either "{plusSign}" or "{minusSign}".
Additionally, the values within the "percent" field must also contain the substring "{percentSign}"; the values within the "currency" field must also contain one or more of the following substrings: "{currencyCode}", "{currencyPrefix}", or "{currencySuffix}"; and the values within the "unit" field must also contain one or more of the following substrings: "{unitPrefix}" or "{unitSuffix}".
The pattern strings, when interpreted as a sequence of UTF-16 encoded code points as described in es2023, , must not contain any code points in the General Category "Number, decimal digit" as specified by the Unicode Standard.
[[LocaleData]].[[<locale>]] must also have a [[notationSubPatterns]] field for all locale values locale. The value of this field must be a Record, which must have two fields: [[scientific]] and [[compact]]. The [[scientific]] field must be a string value containing the substrings "{number}", "{scientificSeparator}", and "{scientificExponent}". The [[compact]] field must be a Record with two fields: "short" and "long". Each of these fields must be a Record with integer keys corresponding to all discrete magnitudes the implementation supports for compact notation. Each of these fields must be a string value which may contain the substring "{number}". Strings descended from "short" must contain the substring "{compactSymbol}", and strings descended from "long" must contain the substring "{compactName}".
Note 2
It is recommended that implementations use the locale data provided by the Common Locale Data Repository (available at https://cldr.unicode.org/).
1.3 Properties of the Intl.NumberFormat Prototype Object
The Intl.NumberFormat prototype object is itself an ordinary object. %NumberFormat.prototype% is not an Intl.NumberFormat instance and does not have an [[InitializedNumberFormat]] internal slot or any of the other internal slots of Intl.NumberFormat instance objects.
1.3.1 Intl.NumberFormat.prototype.constructor
The initial value of Intl.NumberFormat.prototype.constructor is %NumberFormat%.
The initial value of the @@toStringTag property is the String value "Intl.NumberFormat".
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
1.3.3 get Intl.NumberFormat.prototype.format
Intl.NumberFormat.prototype.format is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:
Let nf be the this value.
If the implementation supports the normative optional constructor mode of , then
Let F be a new built-in function object as defined in Number Format Functions (1.5.2).
Set F.[[NumberFormat]] to nf.
Set nf.[[BoundFormat]] to F.
Return nf.[[BoundFormat]].
Note
The returned function is bound to nf so that it can be passed directly to Array.prototype.map or other functions.
This is considered a historical artefact, as part of a convention which is no longer followed for new features, but is preserved to maintain compatibility with existing programs.
1.3.4 Intl.NumberFormat.prototype.formatToParts ( value )
When the formatToParts method is called with an optional argument value, the following steps are taken:
Table 1: Resolved Options of NumberFormat Instances
Internal Slot
Property
[[Locale]]
"locale"
[[NumberingSystem]]
"numberingSystem"
[[Style]]
"style"
[[Currency]]
"currency"
[[CurrencyDisplay]]
"currencyDisplay"
[[CurrencySign]]
"currencySign"
[[Unit]]
"unit"
[[UnitDisplay]]
"unitDisplay"
[[MinimumIntegerDigits]]
"minimumIntegerDigits"
[[MinimumFractionDigits]]
"minimumFractionDigits"
[[MaximumFractionDigits]]
"maximumFractionDigits"
[[MinimumSignificantDigits]]
"minimumSignificantDigits"
[[MaximumSignificantDigits]]
"maximumSignificantDigits"
[[UseGrouping]]
"useGrouping"
[[Notation]]
"notation"
[[CompactDisplay]]
"compactDisplay"
[[SignDisplay]]
"signDisplay"
[[RoundingMode]]
"roundingMode"
[[RoundingIncrement]]
"roundingIncrement"
[[TrailingZeroDisplay]]
"trailingZeroDisplay"
1.4 Properties of Intl.NumberFormat Instances
Intl.NumberFormat instances are ordinary objects that inherit properties from %NumberFormat.prototype%.
Intl.NumberFormat instances have an [[InitializedNumberFormat]] internal slot.
Intl.NumberFormat instances also have several internal slots that are computed by the constructor:
[[Locale]] is a String value with the language tag of the locale whose localization is used for formatting.
[[DataLocale]] is a String value with the language tag of the nearest locale for which the implementation has data to perform the formatting operation. It will be a parent locale of [[Locale]].
[[NumberingSystem]] is a String value with the "type" given in Unicode Technical Standard #35 for the numbering system used for formatting.
[[Style]] is one of the String values "decimal", "currency", "percent", or "unit", identifying the type of quantity being measured.
[[Currency]] is a String value with the currency code identifying the currency to be used if formatting with the "currency" unit type. It is only used when [[Style]] has the value "currency".
[[CurrencyDisplay]] is one of the String values "code", "symbol", "narrowSymbol", or "name", specifying whether to display the currency as an ISO 4217 alphabetic currency code, a localized currency symbol, or a localized currency name if formatting with the "currency" style. It is only used when [[Style]] has the value "currency".
[[CurrencySign]] is one of the String values "standard" or "accounting", specifying whether to render negative numbers in accounting format, often signified by parenthesis. It is only used when [[Style]] has the value "currency" and when [[SignDisplay]] is not "never".
[[Unit]] is a core unit identifier. It is only used when [[Style]] has the value "unit".
[[UnitDisplay]] is one of the String values "short", "narrow", or "long", specifying whether to display the unit as a symbol, narrow symbol, or localized long name if formatting with the "unit" style. It is only used when [[Style]] has the value "unit".
[[MinimumIntegerDigits]] is a non-negative integer Number value indicating the minimum integer digits to be used. Numbers will be padded with leading zeroes if necessary.
[[MinimumFractionDigits]] and [[MaximumFractionDigits]] are non-negative integer Number values indicating the minimum and maximum fraction digits to be used. Numbers will be rounded or padded with trailing zeroes if necessary. These properties are only used when [[RoundingType]] is fractionDigits, morePrecision, or lessPrecision.
[[MinimumSignificantDigits]] and [[MaximumSignificantDigits]] are positive integer Number values indicating the minimum and maximum fraction digits to be shown. If present, the formatter uses however many fraction digits are required to display the specified number of significant digits. These properties are only used when [[RoundingType]] is significantDigits, morePrecision, or lessPrecision.
[[UseGrouping]] is a Boolean or String value indicating the conditions under which a grouping separator should be used. The positions of grouping separators, and whether to display grouping separators for a given number, is implementation-defined. A value "always" hints the implementation to display grouping separators if possible; "min2", if there are at least 2 digits in a group; "auto", if the locale prefers to use grouping separators for the number. A value false disables grouping separators.
[[RoundingType]] is one of the values fractionDigits, significantDigits, morePrecision, or lessPrecision, indicating which rounding strategy to use. If fractionDigits, the number is rounded according to [[MinimumFractionDigits]] and [[MaximumFractionDigits]], as described above. If significantDigits, the number is rounded according to [[MinimumSignificantDigits]] and [[MaximumSignificantDigits]] as described above. If morePrecision or lessPrecision, all four of those settings are used, with specific rules for disambiguating when to use one set versus the other. [[RoundingType]] is derived from the "roundingPriority" option and is converted back to "roundingPriority" in 1.3.7.
[[Notation]] is one of the String values "standard", "scientific", "engineering", or "compact", specifying whether the number should be displayed without scaling, scaled to the units place with the power of ten in scientific notation, scaled to the nearest thousand with the power of ten in scientific notation, or scaled to the nearest locale-dependent compact decimal notation power of ten with the corresponding compact decimal notation affix.
[[CompactDisplay]] is one of the String values "short" or "long", specifying whether to display compact notation affixes in short form ("5K") or long form ("5 thousand") if formatting with the "compact" notation. It is only used when [[Notation]] has the value "compact".
[[SignDisplay]] is one of the String values "auto", "always", "never", "exceptZero", or "negative", specifying when to include a sign (with non-"auto" options respectively corresponding with inclusion always, never, only for nonzero numbers, or only for nonzero negative numbers).
In scientific notation, this slot affects the sign display of the mantissa but not the exponent.
[[RoundingMode]] is one of the String values in the Identifier column of Table 2, specifying which rounding mode to use.
[[RoundingIncrement]] is an integer-valued Number that evenly divides 10, 100, 1000, or 10000 into tenths, fifths, quarters, or halves. It indicates the increment at which rounding should take place relative to the calculated rounding magnitude. For example, if [[MaximumFractionDigits]] is 2 and [[RoundingIncrement]] is 5, then the number is rounded to the nearest 0.05 ("nickel rounding").
[[TrailingZeroDisplay]] is one of the String values "auto" or "stripIfInteger", indicating whether to strip trailing zeros if the formatted number is an integer (i.e., has no nonzero fraction digit).
Table 2: Rounding modes in Intl.NumberFormat
Identifier
Description
Examples: Round to 0 fraction digits
-1.5
0.4
0.5
0.6
1.5
"ceil"
Toward positive infinity
➕ [-1]
➕ [1]
➕ [1]
➕ [1]
➕ [2]
"floor"
Toward negative infinity
➖ [-2]
➖ [0]
➖ [0]
➖ [0]
➖ [1]
"expand"
Away from zero
➖ [-2]
➕ [1]
➕ [1]
➕ [1]
➕ [2]
"trunc"
Toward zero
➕ [-1]
➖ [0]
➖ [0]
➖ [0]
➖ [1]
"halfCeil"
Ties toward positive infinity
➕ [-1]
➖ [0]
➕ [1]
➕ [1]
➕ [2]
"halfFloor"
Ties toward negative infinity
➖ [-2]
➖ [0]
➖ [0]
➕ [1]
➖ [1]
"halfExpand"
Ties away from zero
➖ [-2]
➖ [0]
➕ [1]
➕ [1]
➕ [2]
"halfTrunc"
Ties toward zero
➕ [-1]
➖ [0]
➖ [0]
➕ [1]
➖ [1]
"halfEven"
Ties toward even cardinality
➖ [-2]
➖ [0]
➖ [0]
➕ [1]
➕ [2]
Note
The examples are illustrative of the unique behavior of each option. ➕ means "resolves toward positive infinity"; ➖ means "resolves toward negative infinity".
Finally, Intl.NumberFormat instances have a [[BoundFormat]] internal slot that caches the function returned by the format accessor (1.3.3).
1.5 Abstract Operations for NumberFormat Objects
1.5.1 CurrencyDigits ( currency )
When the CurrencyDigits abstract operation is called with an argument currency (which must be an uppercase String value), the following steps are taken:
If the ISO 4217 currency and funds code list contains currency as an alphabetic code, return the minor unit value corresponding to the currency from the list; otherwise, return 2.
1.5.2 Number Format Functions
A Number format function is an anonymous built-in function that has a [[NumberFormat]] internal slot.
When a Number format function F is called with optional argument value, the following steps are taken:
Let nf be F.[[NumberFormat]].
Assert: Type(nf) is Object and nf has an [[InitializedNumberFormat]] internal slot.
The "length" property of a Number format function is 1.
1.5.3 FormatNumericToString ( intlObject, x )
The FormatNumericToString abstract operation is called with arguments intlObject (which must be an object with [[RoundingMode]], [[RoundingType]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]], [[MaximumFractionDigits]], [[RoundingIncrement]], and [[TrailingZeroDisplay]] internal slots), and x (which must be a mathematical value or negative-zero). It rounds x to an Intl mathematical value according to the internal slots of intlObject and returns a Record with a [[RoundedNumber]] field containing containing that result and a [[FormattedString]] field containing a String value representation of that result formatted according to the internal slots of intlObject.
If x is negative-zero, then
Let isNegative be true.
Set x to 0.
Else,
Assert: x is a mathematical value.
If x < 0, let isNegative be true; else let isNegative be false.
If isNegative is true, then
Set x to -x.
Let unsignedRoundingMode be GetUnsignedRoundingMode(intlObject.[[RoundingMode]], isNegative).
If intlObject.[[RoundingType]] is significantDigits, then
Let result be ToRawPrecision(x, intlObject.[[MinimumSignificantDigits]], intlObject.[[MaximumSignificantDigits]], unsignedRoundingMode).
Else if intlObject.[[RoundingType]] is fractionDigits, then
Let result be ToRawFixed(x, intlObject.[[MinimumFractionDigits]], intlObject.[[MaximumFractionDigits]], intlObject.[[RoundingIncrement]], unsignedRoundingMode).
Else,
Let sResult be ToRawPrecision(x, intlObject.[[MinimumSignificantDigits]], intlObject.[[MaximumSignificantDigits]], unsignedRoundingMode).
Let fResult be ToRawFixed(x, intlObject.[[MinimumFractionDigits]], intlObject.[[MaximumFractionDigits]], intlObject.[[RoundingIncrement]], unsignedRoundingMode).
If intlObj.[[RoundingType]] is morePrecision, then
If sResult.[[RoundingMagnitude]] ≤ fResult.[[RoundingMagnitude]], then
Let result be sResult.
Else,
Let result be fResult.
Else,
Assert: intlObj.[[RoundingType]] is lessPrecision.
If sResult.[[RoundingMagnitude]] ≤ fResult.[[RoundingMagnitude]], then
Let result be fResult.
Else,
Let result be sResult.
Set x to result.[[RoundedNumber]].
Let string be result.[[FormattedString]].
If intlObject.[[TrailingZeroDisplay]] is "stripIfInteger" and x modulo 1 = 0, then
Let i be StringIndexOf(string, ".", 0).
If i ≠ -1, set string to the substring of string from 0 to i.
Let int be result.[[IntegerDigitsCount]].
Let minInteger be intlObject.[[MinimumIntegerDigits]].
If int < minInteger, then
Let forwardZeros be the String consisting of minInteger - int occurrences of the code unit 0x0030 (DIGIT ZERO).
Set string to the string-concatenation of forwardZeros and string.
If isNegative is true, then
If x is 0, set x to negative-zero. Otherwise, set x to -x.
Return the Record { [[RoundedNumber]]: x, [[FormattedString]]: string }.
1.5.4 PartitionNumberPattern ( numberFormat, x )
takes arguments numberFormat (an object initialized as a NumberFormat) and x (an Intl mathematical value). It creates the parts representing the mathematical value of x according to the effective locale and the formatting options of numberFormat. It performs the following steps when called:
Let exponent be 0.
If x is not-a-number, then
Let n be an implementation- and locale-dependent (ILD) String value indicating the NaN value.
Else if x is positive-infinity, then
Let n be an ILD String value indicating positive infinity.
Else if x is negative-infinity, then
Let n be an ILD String value indicating negative infinity.
Else,
If x is not negative-zero,
Assert: x is a mathematical value.
If numberFormat.[[Style]] is "percent", set x be 100 × x.
Append all elements of notationSubParts to result.
Else if p is equal to "plusSign", then
Let plusSignSymbol be the ILND String representing the plus sign.
Append a new Record { [[Type]]: "plusSign", [[Value]]: plusSignSymbol } as the last element of result.
Else if p is equal to "minusSign", then
Let minusSignSymbol be the ILND String representing the minus sign.
Append a new Record { [[Type]]: "minusSign", [[Value]]: minusSignSymbol } as the last element of result.
Else if p is equal to "percentSign" and numberFormat.[[Style]] is "percent", then
Let percentSignSymbol be the ILND String representing the percent sign.
Append a new Record { [[Type]]: "percentSign", [[Value]]: percentSignSymbol } as the last element of result.
Else if p is equal to "unitPrefix" and numberFormat.[[Style]] is "unit", then
Let unit be numberFormat.[[Unit]].
Let unitDisplay be numberFormat.[[UnitDisplay]].
Let mu be an ILD String value representing unit before x in unitDisplay form, which may depend on x in languages having different plural forms.
Append a new Record { [[Type]]: "unit", [[Value]]: mu } as the last element of result.
Else if p is equal to "unitSuffix" and numberFormat.[[Style]] is "unit", then
Let unit be numberFormat.[[Unit]].
Let unitDisplay be numberFormat.[[UnitDisplay]].
Let mu be an ILD String value representing unit after x in unitDisplay form, which may depend on x in languages having different plural forms.
Append a new Record { [[Type]]: "unit", [[Value]]: mu } as the last element of result.
Else if p is equal to "currencyCode" and numberFormat.[[Style]] is "currency", then
Let currency be numberFormat.[[Currency]].
Let cd be currency.
Append a new Record { [[Type]]: "currency", [[Value]]: cd } as the last element of result.
Else if p is equal to "currencyPrefix" and numberFormat.[[Style]] is "currency", then
Let currency be numberFormat.[[Currency]].
Let currencyDisplay be numberFormat.[[CurrencyDisplay]].
Let cd be an ILD String value representing currency before x in currencyDisplay form, which may depend on x in languages having different plural forms.
Append a new Record { [[Type]]: "currency", [[Value]]: cd } as the last element of result.
Else if p is equal to "currencySuffix" and numberFormat.[[Style]] is "currency", then
Let currency be numberFormat.[[Currency]].
Let currencyDisplay be numberFormat.[[CurrencyDisplay]].
Let cd be an ILD String value representing currency after x in currencyDisplay form, which may depend on x in languages having different plural forms. If the implementation does not have such a representation of currency, use currency itself.
Append a new Record { [[Type]]: "currency", [[Value]]: cd } as the last element of result.
Else,
Let unknown be an ILND String based on x and p.
Append a new Record { [[Type]]: "unknown", [[Value]]: unknown } as the last element of result.
Return result.
1.5.5 PartitionNotationSubPattern ( numberFormat, x, n, exponent )
The PartitionNotationSubPattern abstract operation is called with arguments numberFormat (which must be an object initialized as a NumberFormat), x (which is an Intl mathematical value after rounding is applied), n (which is an intermediate formatted string), and exponent (an integer), and creates the corresponding parts for the number and notation according to the effective locale and the formatting options of numberFormat. The following steps are taken:
Let result be a new empty List.
If x is not-a-number, then
Append a new Record { [[Type]]: "nan", [[Value]]: n } as the last element of result.
Else if x is positive-infinity or negative-infinity, then
Append a new Record { [[Type]]: "infinity", [[Value]]: n } as the last element of result.
Let patternParts be PartitionPattern(notationSubPattern).
For each Record { [[Type]], [[Value]] } patternPart of patternParts, do
Let p be patternPart.[[Type]].
If p is "literal", then
Append a new Record { [[Type]]: "literal", [[Value]]: patternPart.[[Value]] } as the last element of result.
Else if p is equal to "number", then
If the numberFormat.[[NumberingSystem]] matches one of the values in the "Numbering System" column of Table 3 below, then
Let digits be a List whose elements are the code points specified in the "Digits" column of the matching row in Table 3.
Assert: The length of digits is 10.
Let transliterated be the empty String.
Let len be the length of n.
Let position be 0.
Repeat, while position < len,
Let c be the code unit at index position within n.
If 0x0030 ≤ c ≤ 0x0039, then
NOTE: c is an ASCII digit.
Let i be c - 0x0030.
Set c to CodePointsToString(« digits[i] »).
Set transliterated to the string-concatenation of transliterated and c.
Set position to position + 1.
Set n to transliterated.
Else use an implementation dependent algorithm to map n to the appropriate representation of n in the given numbering system.
Let decimalSepIndex be StringIndexOf(n, ".", 0).
If decimalSepIndex > 0, then
Let integer be the substring of n from position 0, inclusive, to position decimalSepIndex, exclusive.
Let fraction be the substring of n from position decimalSepIndex, exclusive, to the end of n.
Else,
Let integer be n.
Let fraction be undefined.
If the numberFormat.[[UseGrouping]] is false, then
Append a new Record { [[Type]]: "integer", [[Value]]: integer } as the last element of result.
Else,
Let groupSepSymbol be the implementation-, locale-, and numbering system-dependent (ILND) String representing the grouping separator.
Let groups be a List whose elements are, in left to right order, the substrings defined by ILND set of locations within the integer, which may depend on the value of numberFormat.[[UseGrouping]].
Assert: The number of elements in groups List is greater than 0.
Repeat, while groups List is not empty,
Remove the first element from groups and let integerGroup be the value of that element.
Append a new Record { [[Type]]: "integer", [[Value]]: integerGroup } as the last element of result.
If groups List is not empty, then
Append a new Record { [[Type]]: "group", [[Value]]: groupSepSymbol } as the last element of result.
If fraction is not undefined, then
Let decimalSepSymbol be the ILND String representing the decimal separator.
Append a new Record { [[Type]]: "decimal", [[Value]]: decimalSepSymbol } as the last element of result.
Append a new Record { [[Type]]: "fraction", [[Value]]: fraction } as the last element of result.
Else if p is equal to "compactSymbol", then
Let compactSymbol be an ILD string representing exponent in short form, which may depend on x in languages having different plural forms. The implementation must be able to provide this string, or else the pattern would not have a "{compactSymbol}" placeholder.
Append a new Record { [[Type]]: "compact", [[Value]]: compactSymbol } as the last element of result.
Else if p is equal to "compactName", then
Let compactName be an ILD string representing exponent in long form, which may depend on x in languages having different plural forms. The implementation must be able to provide this string, or else the pattern would not have a "{compactName}" placeholder.
Append a new Record { [[Type]]: "compact", [[Value]]: compactName } as the last element of result.
Else if p is equal to "scientificSeparator", then
Let scientificSeparator be the ILND String representing the exponent separator.
Append a new Record { [[Type]]: "exponentSeparator", [[Value]]: scientificSeparator } as the last element of result.
Else if p is equal to "scientificExponent", then
If exponent < 0, then
Let minusSignSymbol be the ILND String representing the minus sign.
Append a new Record { [[Type]]: "exponentMinusSign", [[Value]]: minusSignSymbol } as the last element of result.
Let exponent be -exponent.
Let exponentResult be ToRawFixed(exponent, 0, 0, 1, undefined).
Append a new Record { [[Type]]: "exponentInteger", [[Value]]: exponentResult.[[FormattedString]] } as the last element of result.
Else,
Let unknown be an ILND String based on x and p.
Append a new Record { [[Type]]: "unknown", [[Value]]: unknown } as the last element of result.
Return result.
Table 3: Numbering systems with simple digit mappings
The computations rely on String values and locations within numeric strings that are dependent upon the implementation and the effective locale of numberFormat ("ILD") or upon the implementation, the effective locale, and the numbering system of numberFormat ("ILND"). The ILD and ILND Strings mentioned, other than those for currency names, must not contain any code points in the General Category "Number, decimal digit" as specified by the Unicode Standard.
Note 2
It is recommended that implementations use the locale provided by the Common Locale Data Repository (available at https://cldr.unicode.org/).
1.5.6 FormatNumeric ( numberFormat, x )
The FormatNumeric abstract operation is called with arguments numberFormat (which must be an object initialized as a NumberFormat) and x (which must be an Intl mathematical value), and performs the following steps:
For each Record { [[Type]], [[Value]] } part in parts, do
Set result to the string-concatenation of result and part.[[Value]].
Return result.
1.5.7 FormatNumericToParts ( numberFormat, x )
The FormatNumericToParts abstract operation is called with arguments numberFormat (which must be an object initialized as a NumberFormat) and x (which must be an Intl mathematical value), and performs the following steps:
ToRawPrecision is an abstract operation that involves solving the following equation, which returns a valid mathematical value given integer inputs:
ToRawPrecisionFn(n, e, p) = n × 10e–p+1
where 10p–1 ≤ n < 10p
When the ToRawPrecision abstract operation is called with arguments x (which must be a finite non-negative mathematical value), minPrecision, maxPrecision (both must be integers between 1 and 21), and unsignedRoundingMode (a specification type from the Unsigned Rounding Mode column of Table 4 or undefined), the following steps are taken:
Let p be maxPrecision.
If x = 0, then
Let m be the String consisting of p occurrences of the code unit 0x0030 (DIGIT ZERO).
Let e be 0.
Let xFinal be 0.
Else,
Let n1 and e1 each be an integer and r1 a mathematical value, with r1 = ToRawPrecisionFn(n1, e1, p), such that r1 ≤ x and r1 is maximized.
Let n2 and e2 each be an integer and r2 a mathematical value, with r2 = ToRawPrecisionFn(n2, e2, p), such that r2 ≥ x and r2 is minimized.
ToRawFixed is an abstract operation that involves solving the following equation, which returns a valid mathematical value given integer inputs:
ToRawFixedFn(n, f) = n × 10–f
When the ToRawFixed abstract operation is called with arguments x (which must be a finite non-negative mathematical value), minFraction, maxFraction (which must be integers between 0 and 20), roundingIncrement (an integer), and unsignedRoundingMode (a specification type from the Unsigned Rounding Mode column of Table 4 or undefined), the following steps are taken:
Let f be maxFraction.
Let n1 be an integer and r1 a mathematical value, with r1 = ToRawFixedFn(n1, f), such that n1 modulo roundingIncrement = 0, r1 ≤ x, and r1 is maximized.
Let n2 be an integer and r2 a mathematical value, with r2 = ToRawFixedFn(n2, f), such that n2 modulo roundingIncrement = 0, r2 ≥ x, and r2 is minimized.
If n = 0, let m be "0". Otherwise, let m be the String consisting of the digits of the decimal representation of n (in order, with no leading zeroes).
If f ≠ 0, then
Let k be the length of m.
If k ≤ f, then
Let z be the String value consisting of f + 1 - k occurrences of the code unit 0x0030 (DIGIT ZERO).
Set m to the string-concatenation of z and m.
Set k to f + 1.
Let a be the first k - f code units of m, and let b be the remaining f code units of m.
Set m to the string-concatenation of a, ".", and b.
Let int be the length of a.
Else, let int be the length of m.
Let cut be maxFraction - minFraction.
Repeat, while cut > 0 and the last code unit of m is 0x0030 (DIGIT ZERO),
Remove the last code unit from m.
Decrease cut by 1.
If the last code unit of m is 0x002E (FULL STOP), then
Remove the last code unit from m.
Return the Record { [[FormattedString]]: m, [[RoundedNumber]]: xFinal, [[IntegerDigitsCount]]: int, [[RoundingMagnitude]]: –f }.
1.5.10 UnwrapNumberFormat ( nf )
The UnwrapNumberFormat abstract operation returns the NumberFormat instance
of its input object, which is either the value itself or a value associated
with it by %NumberFormat% according to the normative optional
constructor mode of .
If Type(nf) is not Object, throw a TypeError exception.
If nf does not have an [[InitializedNumberFormat]] internal slot and ? OrdinaryHasInstance(%NumberFormat%, nf) is true, then
Return ? Get(nf, %Intl%.[[FallbackSymbol]]).
Return nf.
1.5.11 GetNumberFormatPattern ( numberFormat, x )
The abstract operation GetNumberFormatPattern considers the resolved unit-related options in the number format object along with the final scaled and rounded number being formatted (an Intl mathematical value) and returns a pattern, a String value as described in 1.2.3.
The abstract operation GetNotationSubPattern considers the resolved notation and exponent, and returns a String value for the notation sub pattern as described in 1.2.3.
Let dataLocaleData be localeData.[[<dataLocale>]].
Let notationSubPatterns be dataLocaleData.[[notationSubPatterns]].
Assert: notationSubPatterns is a Record (see 1.2.3).
Let notation be numberFormat.[[Notation]].
If notation is "scientific" or notation is "engineering", then
Return notationSubPatterns.[[scientific]].
Else if exponent is not 0, then
Assert: notation is "compact".
Let compactDisplay be numberFormat.[[CompactDisplay]].
Let compactPatterns be notationSubPatterns.[[compact]].[[<compactDisplay>]].
Return compactPatterns.[[<exponent>]].
Else,
Return "{number}".
1.5.13 ComputeExponent ( numberFormat, x )
The abstract operation ComputeExponent computes an exponent (power of ten) by which to scale x according to the number formatting settings.
It handles cases such as 999 rounding up to 1000, requiring a different exponent.
If x = 0, then
Return 0.
If x < 0, then
Let x = -x.
Let magnitude be the base 10 logarithm of x rounded down to the nearest integer.
The abstract operation ComputeExponentForMagnitude computes an exponent by which to scale a number of the given magnitude (power of ten of the most significant digit) according to the locale and the desired notation (scientific, engineering, or compact).
Let notation be numberFormat.[[Notation]].
If notation is "standard", then
Return 0.
Else if notation is "scientific", then
Return magnitude.
Else if notation is "engineering", then
Let thousands be the greatest integer that is not greater than magnitude / 3.
Return thousands × 3.
Else,
Assert: notation is "compact".
Let exponent be an implementation- and locale-dependent (ILD) integer by which to scale a number of the given magnitude in compact notation for the current locale.
Return exponent.
1.5.15 Runtime Semantics: StringIntlMV
The syntax-directed operation StringIntlMV takes no arguments.
Note
The conversion of a StringNumericLiteral to a Number value is similar overall to the determination of the NumericValue of a NumericLiteral (see ), but some of the details are different.
It is defined piecewise over the following productions:
If ExponentPart is present, let e be MV of ExponentPart. Otherwise, let e be 0.
Return a × 10e.
1.5.16 ToIntlMathematicalValue ( value )
The abstract operation ToIntlMathematicalValue takes argument value. It returns value converted to an Intl mathematical value, which is a mathematical value together with positive-infinity, negative-infinity, not-a-number, and negative-zero. This abstract operation is similar to , but a mathematical value can be returned instead of a Number or BigInt, so that exact decimal values can be represented. The following steps are taken:
Let primValue be ? ToPrimitive(value, number).
If Type(primValue) is BigInt, return ℝ(primValue).
If Type(primValue) is String,
Let str be primValue.
Else,
Let x be ? ToNumber(primValue).
If x is -0𝔽, return negative-zero.
Let str be ! Number::toString(x).
Let text be ! StringToCodePoints(str).
Let literal be ParseText(text, StringNumericLiteral).
If literal is a List of errors, return not-a-number.
The abstract operation GetUnsignedRoundingMode returns the rounding mode that should be applied to the absolute value of a number to produce the same result as if roundingMode, one of the String values in the Identifier column of Table 2, were applied to the signed value of the number (negative if the boolean isNegative is true, or positive otherwise). The following steps are taken:
If isNegative is true, return the specification type in the third column of Table 4 where the first column is roundingMode and the second column is "negative".
Else, return the specification type in the third column of Table 4 where the first column is roundingMode and the second column is "positive".
Table 4: Conversion from rounding mode to unsigned rounding mode
The abstract operation ApplyUnsignedRoundingMode considers x (a mathematical value), bracketed below by r1 (a mathematical value) and above by r2 (a mathematical value), and returns either r1 or r2 according to unsignedRoundingMode (a specification type from the Unsigned Rounding Mode column of Table 4 or undefined). The following steps are taken:
If x is equal to r1, return r1.
Assert: r1 < x < r2.
Assert: unsignedRoundingMode is not undefined.
If unsignedRoundingMode is zero, return r1.
If unsignedRoundingMode is infinity, return r2.
Let d1 be x – r1.
Let d2 be r2 – x.
If d1 < d2, return r1.
If d2 < d1, return r2.
Assert: d1 is equal to d2.
If unsignedRoundingMode is half-zero, return r1.
If unsignedRoundingMode is half-infinity, return r2.
Assert: unsignedRoundingMode is half-even.
Let cardinality be (r1 / (r2 – r1)) modulo 2.
If cardinality is 0, return r1.
Return r2.
1.5.19 PartitionNumberRangePattern ( numberFormat, x, y )
The abstract operation PartitionNumberRangePattern creates the parts for a localized number range according to x (which must be an Intl mathematical value), y (which must be an Intl mathematical value), and the formatting options of numberFormat (which must be an object initialized as NumberFormat). The following steps are taken:
If x is not-a-number or y is not-a-number, throw a RangeError exception.
1.5.20 FormatApproximately ( numberFormat, result )
The FormatApproximately abstract operation modifies result, which must be a List of Record values as described in PartitionNumberPattern, by adding a new Record for the approximately sign, which may depend on numberFormat (which must be an object initialized as NumberFormat). The following steps are taken:
Let i be an index into result, determined by an implementation-defined algorithm based on numberFormat and result.
Let approximatelySign be an ILND String value used to signify that a number is approximate.
If approximatelySign is not empty, insert a new Record { [[Type]]: "approximatelySign", [[Value]]: approximatelySign } at index i in result.
Return result.
1.5.21 CollapseNumberRange ( result )
The CollapseNumberRange abstract operation modifies result, which must be a List of Record values as described in PartitionNumberRangePattern, by removing redundant information, and returns the resulting List. The algorithm is implementation dependent, but it must not introduce ambiguity: the resulting list after modification should be unique for all pairs x and y.
For example, an implementation may choose to remove the currency symbol following the range separator, to produce "$3–5" instead of "$3–$5".
The implementation may choose to modify symbols for grammatical correctness; for example, "0.5 miles–1 mile" may become "0.5–1 miles".
Returning result unmodified is guaranteed to be a correct implementation of CollapseNumberRange.
1.5.22 FormatNumericRange( numberFormat, x, y )
The FormatNumericRange abstract operation is called with arguments numberFormat (which must be an object initialized as a NumberFormat), x (which must be an Intl mathematical value), and y (which must be an Intl mathematical value greater than or equal to x), and performs the following steps:
Set result to the string-concatenation of result and part.[[Value]].
Return result.
1.5.23 FormatNumericRangeToParts( numberFormat, x, y )
The FormatNumericRangeToParts abstract operation is called with arguments numberFormat (which must be an object initialized as a NumberFormat), x (which must be an Intl mathematical value), and y (which must be an Intl mathematical value greater than or equal to x), and performs the following steps: