16.5
Abstract Operations for NumberFormat Objects
16.5.1
CurrencyDigits (
currency
The
implementation-defined
abstract operation CurrencyDigits takes argument
currency
(a String) and returns a non-negative
integer
. It performs the following steps when called:
1.
Assert
IsWellFormedCurrencyCode
currency
) is
true
2.
Return a non-negative
integer
indicating the number of fractional digits used when formatting quantities of the currency corresponding to
currency
. If there is no available information on the number of digits to be used, return 2.
16.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
is called with optional argument
value
, the following steps are taken:
1.
Let
nf
be
[[NumberFormat]]
2.
Assert
nf
is an Object
and
nf
has an
[[InitializedNumberFormat]]
internal slot.
3.
If
value
is not provided, let
value
be
undefined
4.
Let
be ?
ToIntlMathematicalValue
value
).
5.
Return
FormatNumeric
nf
).
The
"length"
property of a Number format function is
16.5.3
FormatNumericToString (
intlObject
The abstract operation FormatNumericToString takes arguments
intlObject
(an Object) and
(a
mathematical value
or
negative-zero
) and returns a
Record
with fields
[[RoundedNumber]]
(a
mathematical value
or
negative-zero
) and
[[FormattedString]]
(a String). It rounds
to an
Intl mathematical value
according to the internal slots of
intlObject
. The
[[RoundedNumber]]
field contains the rounded result value and the
[[FormattedString]]
field contains a String value representation of that result formatted according to the internal slots of
intlObject
. It performs the following steps when called:
1.
Assert
intlObject
has
[[RoundingMode]]
[[RoundingType]]
[[MinimumSignificantDigits]]
[[MaximumSignificantDigits]]
[[MinimumIntegerDigits]]
[[MinimumFractionDigits]]
[[MaximumFractionDigits]]
[[RoundingIncrement]]
, and
[[TrailingZeroDisplay]]
internal slots.
2.
If
is
negative-zero
, then
a.
Let
sign
be
negative
b.
Set
to 0.
3.
Else,
a.
Assert
is a
mathematical value
b.
If
< 0, let
sign
be
negative
; else let
sign
be
positive
c.
If
sign
is
negative
, then
i.
Set
to -
4.
Let
unsignedRoundingMode
be
GetUnsignedRoundingMode
intlObject
[[RoundingMode]]
sign
).
5.
If
intlObject
[[RoundingType]]
is
significant-digits
, then
a.
Let
result
be
ToRawPrecision
intlObject
[[MinimumSignificantDigits]]
intlObject
[[MaximumSignificantDigits]]
unsignedRoundingMode
).
6.
Else if
intlObject
[[RoundingType]]
is
fraction-digits
, then
a.
Let
result
be
ToRawFixed
intlObject
[[MinimumFractionDigits]]
intlObject
[[MaximumFractionDigits]]
intlObject
[[RoundingIncrement]]
unsignedRoundingMode
).
7.
Else,
a.
Let
sResult
be
ToRawPrecision
intlObject
[[MinimumSignificantDigits]]
intlObject
[[MaximumSignificantDigits]]
unsignedRoundingMode
).
b.
Let
fResult
be
ToRawFixed
intlObject
[[MinimumFractionDigits]]
intlObject
[[MaximumFractionDigits]]
intlObject
[[RoundingIncrement]]
unsignedRoundingMode
).
c.
If
fResult
[[RoundingMagnitude]]
sResult
[[RoundingMagnitude]]
, let
fixedIsMorePrecise
be
true
; else let
fixedIsMorePrecise
be
false
d.
If
intlObject
[[RoundingType]]
is
more-precision
and
fixedIsMorePrecise
is
true
, then
i.
Let
result
be
fResult
e.
Else if
intlObject
[[RoundingType]]
is
less-precision
and
fixedIsMorePrecise
is
false
, then
i.
Let
result
be
fResult
f.
Else,
i.
Let
result
be
sResult
8.
Set
to
result
[[RoundedNumber]]
9.
Let
string
be
result
[[FormattedString]]
10.
If
intlObject
[[TrailingZeroDisplay]]
is
"stripIfInteger"
and
modulo
1 = 0
, then
a.
Let
be
StringIndexOf
string
"."
, 0).
b.
If
is not
not-found
, set
string
to the
substring
of
string
from 0 to
11.
Let
int
be
result
[[IntegerDigitsCount]]
12.
Let
minInteger
be
intlObject
[[MinimumIntegerDigits]]
13.
If
int
minInteger
, then
a.
Let
forwardZeros
be the String consisting of
minInteger
int
occurrences of the code unit 0x0030 (DIGIT ZERO).
b.
Set
string
to the
string-concatenation
of
forwardZeros
and
string
14.
If
sign
is
negative
, then
a.
If
is 0, set
to
negative-zero
. Otherwise, set
to -
15.
Return the
Record
[[RoundedNumber]]
[[FormattedString]]
string
}.
16.5.4
PartitionNumberPattern (
numberFormat
The abstract operation PartitionNumberPattern takes arguments
numberFormat
(an object initialized as a NumberFormat) and
(an
Intl mathematical value
) and returns a
List
of
Records
with fields
[[Type]]
(a String) and
[[Value]]
(a String). It creates the parts representing the
mathematical value of
according to the effective locale and the formatting options of
numberFormat
. It performs the following steps when called:
1.
Let
exponent
be 0.
2.
If
is
not-a-number
, then
a.
Let
be an
ILD
String value indicating the
NaN
value.
3.
Else if
is
positive-infinity
, then
a.
Let
be an
ILD
String value indicating positive infinity.
4.
Else if
is
negative-infinity
, then
a.
Let
be an
ILD
String value indicating negative infinity.
5.
Else,
a.
If
is not
negative-zero
, then
i.
Assert
is a
mathematical value
ii.
If
numberFormat
[[Style]]
is
"percent"
, set
be 100 ×
iii.
Set
exponent
to
ComputeExponent
numberFormat
).
iv.
Set
to
× 10
**
exponent
b.
Let
formatNumberResult
be
FormatNumericToString
numberFormat
).
c.
Let
be
formatNumberResult
[[FormattedString]]
d.
Set
to
formatNumberResult
[[RoundedNumber]]
6.
Let
pattern
be
GetNumberFormatPattern
numberFormat
).
7.
Let
result
be a new empty
List
8.
Let
patternParts
be
PartitionPattern
pattern
).
9.
For each
Record
[[Type]]
[[Value]]
patternPart
of
patternParts
, do
a.
Let
be
patternPart
[[Type]]
b.
If
is
"literal"
, then
i.
Append the
Record
[[Type]]
"literal"
[[Value]]
patternPart
[[Value]]
} to
result
c.
Else if
is
"number"
, then
i.
Let
notationSubParts
be
PartitionNotationSubPattern
numberFormat
exponent
).
ii.
Set
result
to the
list-concatenation
of
result
and
notationSubParts
d.
Else if
is
"plusSign"
, then
i.
Let
plusSignSymbol
be the
ILND
String representing the plus sign.
ii.
Append the
Record
[[Type]]
"plusSign"
[[Value]]
plusSignSymbol
} to
result
e.
Else if
is
"minusSign"
, then
i.
Let
minusSignSymbol
be the
ILND
String representing the minus sign.
ii.
Append the
Record
[[Type]]
"minusSign"
[[Value]]
minusSignSymbol
} to
result
f.
Else if
is
"percentSign"
and
numberFormat
[[Style]]
is
"percent"
, then
i.
Let
percentSignSymbol
be the
ILND
String representing the percent sign.
ii.
Append the
Record
[[Type]]
"percentSign"
[[Value]]
percentSignSymbol
} to
result
g.
Else if
is
"unitPrefix"
and
numberFormat
[[Style]]
is
"unit"
, then
i.
Let
unit
be
numberFormat
[[Unit]]
ii.
Let
unitDisplay
be
numberFormat
[[UnitDisplay]]
iii.
Let
mu
be an
ILD
String value representing
unit
before
in
unitDisplay
form, which may depend on
in languages having different plural forms.
iv.
Append the
Record
[[Type]]
"unit"
[[Value]]
mu
} to
result
h.
Else if
is
"unitSuffix"
and
numberFormat
[[Style]]
is
"unit"
, then
i.
Let
unit
be
numberFormat
[[Unit]]
ii.
Let
unitDisplay
be
numberFormat
[[UnitDisplay]]
iii.
Let
mu
be an
ILD
String value representing
unit
after
in
unitDisplay
form, which may depend on
in languages having different plural forms.
iv.
Append the
Record
[[Type]]
"unit"
[[Value]]
mu
} to
result
i.
Else if
is
"currencyCode"
and
numberFormat
[[Style]]
is
"currency"
, then
i.
Let
currency
be
numberFormat
[[Currency]]
ii.
Let
cd
be
currency
iii.
Append the
Record
[[Type]]
"currency"
[[Value]]
cd
} to
result
j.
Else if
is
"currencyPrefix"
and
numberFormat
[[Style]]
is
"currency"
, then
i.
Let
currency
be
numberFormat
[[Currency]]
ii.
Let
currencyDisplay
be
numberFormat
[[CurrencyDisplay]]
iii.
Let
cd
be an
ILD
String value representing
currency
before
in
currencyDisplay
form, which may depend on
in languages having different plural forms.
iv.
Append the
Record
[[Type]]
"currency"
[[Value]]
cd
} to
result
k.
Else if
is
"currencySuffix"
and
numberFormat
[[Style]]
is
"currency"
, then
i.
Let
currency
be
numberFormat
[[Currency]]
ii.
Let
currencyDisplay
be
numberFormat
[[CurrencyDisplay]]
iii.
Let
cd
be an
ILD
String value representing
currency
after
in
currencyDisplay
form, which may depend on
in languages having different plural forms. If the implementation does not have such a representation of
currency
, use
currency
itself.
iv.
Append the
Record
[[Type]]
"currency"
[[Value]]
cd
} to
result
l.
Else,
i.
Let
unknown
be an
ILND
String based on
and
ii.
Append the
Record
[[Type]]
"unknown"
[[Value]]
unknown
} to
result
10.
Return
result
16.5.5
PartitionNotationSubPattern (
numberFormat
exponent
The abstract operation PartitionNotationSubPattern takes arguments
numberFormat
(an Intl.NumberFormat),
(an
Intl mathematical value
),
(a String), and
exponent
(an
integer
) and returns a
List
of
Records
with fields
[[Type]]
(a String) and
[[Value]]
(a String).
is an
Intl mathematical value
after rounding is applied and
is an intermediate formatted string.
It creates the corresponding parts for the number and notation
according to the effective locale and the formatting options of
numberFormat
It performs the following steps when called:
1.
Let
result
be a new empty
List
2.
If
is
not-a-number
, then
a.
Append the
Record
[[Type]]
"nan"
[[Value]]
} to
result
3.
Else if
is
positive-infinity
or
negative-infinity
, then
a.
Append the
Record
[[Type]]
"infinity"
[[Value]]
} to
result
4.
Else,
a.
Let
notationSubPattern
be
GetNotationSubPattern
numberFormat
exponent
).
b.
Let
patternParts
be
PartitionPattern
notationSubPattern
).
c.
For each
Record
[[Type]]
[[Value]]
patternPart
of
patternParts
, do
i.
Let
be
patternPart
[[Type]]
ii.
If
is
"literal"
, then
1.
Append the
Record
[[Type]]
"literal"
[[Value]]
patternPart
[[Value]]
} to
result
iii.
Else if
is
"number"
, then
1.
If the
numberFormat
[[NumberingSystem]]
matches one of the values in the Numbering System column of
Table 28
below, then
a.
Let
digits
be a
List
whose elements are the code points specified in the Digits column of the matching row in
Table 28
b.
Assert
: The length of
digits
is 10.
c.
Let
transliterated
be the empty String.
d.
Let
len
be the length of
e.
Let
position
be 0.
f.
Repeat, while
position
len
i.
Let
be the code unit at index
position
within
ii.
If 0x0030 ≤
≤ 0x0039, then
i.
NOTE:
is an ASCII digit.
ii.
Let
be
- 0x0030.
iii.
Set
to
CodePointsToString
(«
digits
] »).
iii.
Set
transliterated
to the
string-concatenation
of
transliterated
and
iv.
Set
position
to
position
+ 1.
g.
Set
to
transliterated
2.
Else,
a.
Use an implementation dependent algorithm to map
to the appropriate representation of
in the given numbering system.
3.
Let
decimalSepIndex
be
StringIndexOf
"."
, 0).
4.
If
decimalSepIndex
is not
not-found
and
decimalSepIndex
> 0, then
a.
Let
integer
be the
substring
of
from 0 to
decimalSepIndex
b.
Let
fraction
be the
substring
of
from
decimalSepIndex
+ 1.
5.
Else,
a.
Let
integer
be
b.
Let
fraction
be
undefined
6.
If the
numberFormat
[[UseGrouping]]
is
false
, then
a.
Append the
Record
[[Type]]
"integer"
[[Value]]
integer
} to
result
7.
Else,
a.
Let
groupSepSymbol
be the
ILND
String representing the grouping separator.
b.
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]]
c.
Assert
: The number of elements in
groups
List
is greater than 0.
d.
Repeat, while
groups
List
is not empty,
i.
Remove the first element from
groups
and let
integerGroup
be the value of that element.
ii.
Append the
Record
[[Type]]
"integer"
[[Value]]
integerGroup
} to
result
iii.
If
groups
List
is not empty, then
i.
Append the
Record
[[Type]]
"group"
[[Value]]
groupSepSymbol
} to
result
8.
If
fraction
is not
undefined
, then
a.
Let
decimalSepSymbol
be the
ILND
String representing the decimal separator.
b.
Append the
Record
[[Type]]
"decimal"
[[Value]]
decimalSepSymbol
} to
result
c.
Append the
Record
[[Type]]
"fraction"
[[Value]]
fraction
} to
result
iv.
Else if
is
"compactSymbol"
, then
1.
Let
compactSymbol
be an
ILD
string representing
exponent
in short form, which may depend on
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.
2.
Append the
Record
[[Type]]
"compact"
[[Value]]
compactSymbol
} to
result
v.
Else if
is
"compactName"
, then
1.
Let
compactName
be an
ILD
string representing
exponent
in long form, which may depend on
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.
2.
Append the
Record
[[Type]]
"compact"
[[Value]]
compactName
} to
result
vi.
Else if
is
"scientificSeparator"
, then
1.
Let
scientificSeparator
be the
ILND
String representing the exponent separator.
2.
Append the
Record
[[Type]]
"exponentSeparator"
[[Value]]
scientificSeparator
} to
result
vii.
Else if
is
"scientificExponent"
, then
1.
If
exponent
< 0, then
a.
Let
minusSignSymbol
be the
ILND
String representing the minus sign.
b.
Append the
Record
[[Type]]
"exponentMinusSign"
[[Value]]
minusSignSymbol
} to
result
c.
Let
exponent
be -
exponent
2.
Let
exponentResult
be
ToRawFixed
exponent
, 0, 0, 1,
undefined
).
3.
Append the
Record
[[Type]]
"exponentInteger"
[[Value]]
exponentResult
[[FormattedString]]
} to
result
viii.
Else,
1.
Let
unknown
be an
ILND
String based on
and
2.
Append the
Record
[[Type]]
"unknown"
[[Value]]
unknown
} to
result
5.
Return
result
Table 28: Numbering systems with simple digit mappings
Numbering System
Digits
adlm
U+1E950 to U+1E959
ahom
U+11730 to U+11739
arab
U+0660 to U+0669
arabext
U+06F0 to U+06F9
bali
U+1B50 to U+1B59
beng
U+09E6 to U+09EF
bhks
U+11C50 to U+11C59
brah
U+11066 to U+1106F
cakm
U+11136 to U+1113F
cham
U+AA50 to U+AA59
deva
U+0966 to U+096F
diak
U+11950 to U+11959
fullwide
U+FF10 to U+FF19
gara
U+10D40 to U+10D49
gong
U+11DA0 to U+11DA9
gonm
U+11D50 to U+11D59
gujr
U+0AE6 to U+0AEF
gukh
U+16130 to U+16139
guru
U+0A66 to U+0A6F
hanidec
U+3007, U+4E00, U+4E8C, U+4E09, U+56DB, U+4E94, U+516D, U+4E03, U+516B, U+4E5D
hmng
U+16B50 to U+16B59
hmnp
U+1E140 to U+1E149
java
U+A9D0 to U+A9D9
kali
U+A900 to U+A909
kawi
U+11F50 to U+11F59
khmr
U+17E0 to U+17E9
knda
U+0CE6 to U+0CEF
krai
U+16D70 to U+16D79
lana
U+1A80 to U+1A89
lanatham
U+1A90 to U+1A99
laoo
U+0ED0 to U+0ED9
latn
U+0030 to U+0039
lepc
U+1C40 to U+1C49
limb
U+1946 to U+194F
mathbold
U+1D7CE to U+1D7D7
mathdbl
U+1D7D8 to U+1D7E1
mathmono
U+1D7F6 to U+1D7FF
mathsanb
U+1D7EC to U+1D7F5
mathsans
U+1D7E2 to U+1D7EB
mlym
U+0D66 to U+0D6F
modi
U+11650 to U+11659
mong
U+1810 to U+1819
mroo
U+16A60 to U+16A69
mtei
U+ABF0 to U+ABF9
mymr
U+1040 to U+1049
mymrepka
U+116DA to U+116E3
mymrpao
U+116D0 to U+116D9
mymrshan
U+1090 to U+1099
mymrtlng
U+A9F0 to U+A9F9
nagm
U+1E4F0 to U+1E4F9
newa
U+11450 to U+11459
nkoo
U+07C0 to U+07C9
olck
U+1C50 to U+1C59
onao
U+1E5F1 to U+1E5FA
orya
U+0B66 to U+0B6F
osma
U+104A0 to U+104A9
outlined
U+1CCF0 to U+1CCF9
rohg
U+10D30 to U+10D39
saur
U+A8D0 to U+A8D9
segment
U+1FBF0 to U+1FBF9
shrd
U+111D0 to U+111D9
sind
U+112F0 to U+112F9
sinh
U+0DE6 to U+0DEF
sora
U+110F0 to U+110F9
sund
U+1BB0 to U+1BB9
sunu
U+11BF0 to U+11BF9
takr
U+116C0 to U+116C9
talu
U+19D0 to U+19D9
tamldec
U+0BE6 to U+0BEF
telu
U+0C66 to U+0C6F
thai
U+0E50 to U+0E59
tibt
U+0F20 to U+0F29
tirh
U+114D0 to U+114D9
tnsa
U+16AC0 to U+16AC9
vaii
U+A620 to U+A629
wara
U+118E0 to U+118E9
wcho
U+1E2F0 to U+1E2F9
Note 1
The computations rely on
ILD
and
ILND
String values and locations within numeric strings that depend on the effective locale of
numberFormat
, or upon the effective locale and numbering system of
numberFormat
. The
ILD
and
ILND
String values 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
).
16.5.6
FormatNumeric (
numberFormat
The abstract operation FormatNumeric takes arguments
numberFormat
(an Intl.NumberFormat) and
(an
Intl mathematical value
) and returns a String. It performs the following steps when called:
1.
Let
parts
be
PartitionNumberPattern
numberFormat
).
2.
Let
result
be the empty String.
3.
For each
Record
[[Type]]
[[Value]]
part
of
parts
, do
a.
Set
result
to the
string-concatenation
of
result
and
part
[[Value]]
4.
Return
result
16.5.7
FormatNumericToParts (
numberFormat
The abstract operation FormatNumericToParts takes arguments
numberFormat
(an Intl.NumberFormat) and
(an
Intl mathematical value
) and returns an Array. It performs the following steps when called:
1.
Let
parts
be
PartitionNumberPattern
numberFormat
).
2.
Let
result
be !
ArrayCreate
(0).
3.
Let
be 0.
4.
For each
Record
[[Type]]
[[Value]]
part
of
parts
, do
a.
Let
be
OrdinaryObjectCreate
%Object.prototype%
).
b.
Perform !
CreateDataPropertyOrThrow
"type"
part
[[Type]]
).
c.
Perform !
CreateDataPropertyOrThrow
"value"
part
[[Value]]
).
d.
Perform !
CreateDataPropertyOrThrow
result
, !
ToString
)),
).
e.
Increment
by 1.
5.
Return
result
16.5.8
ToRawPrecision (
minPrecision
maxPrecision
unsignedRoundingMode
The abstract operation ToRawPrecision takes arguments
(a non-negative
mathematical value
),
minPrecision
(an
integer
in the
inclusive interval
from 1 to 21),
maxPrecision
(an
integer
in the
inclusive interval
from 1 to 21), and
unsignedRoundingMode
(a specification type from the Unsigned Rounding Mode column of
Table 29
, or
undefined
) and returns a
Record
with fields
[[FormattedString]]
(a String),
[[RoundedNumber]]
(a
mathematical value
),
[[IntegerDigitsCount]]
(an
integer
), and
[[RoundingMagnitude]]
(an
integer
).
It involves solving the following equation, which returns a valid
mathematical value
given
integer
inputs:
ToRawPrecisionFn(
) =
× 10
**(
+1
where 10
**(
–1
< 10
**
It performs the following steps when called:
1.
Let
be
maxPrecision
2.
If
= 0, then
a.
Let
be the String consisting of
occurrences of the code unit 0x0030 (DIGIT ZERO).
b.
Let
be 0.
c.
Let
xFinal
be 0.
3.
Else,
a.
Let
n1
and
e1
each be an
integer
and
r1
mathematical value
, with
r1
ToRawPrecisionFn
n1
e1
, such that
r1
and
r1
is maximized.
b.
Let
n2
and
e2
each be an
integer
and
r2
mathematical value
, with
r2
ToRawPrecisionFn
n2
e2
, such that
r2
and
r2
is minimized.
c.
Let
xFinal
be
ApplyUnsignedRoundingMode
r1
r2
unsignedRoundingMode
).
d.
If
xFinal
is
r1
, then
i.
Let
be
n1
ii.
Let
be
e1
e.
Else,
i.
Let
be
n2
ii.
Let
be
e2
f.
Let
be the String consisting of the digits of the decimal representation of
(in order, with no leading zeroes).
4.
If
≥ (
- 1), then
a.
Set
to the
string-concatenation
of
and
+ 1 occurrences of the code unit 0x0030 (DIGIT ZERO).
b.
Let
int
be
+ 1.
5.
Else if
≥ 0, then
a.
Set
to the
string-concatenation
of the first
+ 1 code units of
, the code unit 0x002E (FULL STOP), and the remaining
- (
+ 1) code units of
b.
Let
int
be
+ 1.
6.
Else,
a.
Assert
< 0.
b.
Set
to the
string-concatenation
of
"0."
, -(
+ 1) occurrences of the code unit 0x0030 (DIGIT ZERO), and
c.
Let
int
be 1.
7.
If
contains the code unit 0x002E (FULL STOP) and
maxPrecision
minPrecision
, then
a.
Let
cut
be
maxPrecision
minPrecision
b.
Repeat, while
cut
> 0 and the last code unit of
is 0x0030 (DIGIT ZERO),
i.
Remove the last code unit from
ii.
Set
cut
to
cut
- 1.
c.
If the last code unit of
is 0x002E (FULL STOP), then
i.
Remove the last code unit from
8.
Return the
Record
[[FormattedString]]
[[RoundedNumber]]
xFinal
[[IntegerDigitsCount]]
int
[[RoundingMagnitude]]
+1 }.
16.5.9
ToRawFixed (
minFraction
maxFraction
roundingIncrement
unsignedRoundingMode
The abstract operation ToRawFixed takes arguments
(a non-negative
mathematical value
),
minFraction
(an
integer
in the
inclusive interval
from 0 to 100),
maxFraction
(an
integer
in the
inclusive interval
from 0 to 100),
roundingIncrement
(an
integer
), and
unsignedRoundingMode
(a specification type from the Unsigned Rounding Mode column of
Table 29
, or
undefined
) and returns a
Record
with fields
[[FormattedString]]
(a String),
[[RoundedNumber]]
(a
mathematical value
),
[[IntegerDigitsCount]]
(an
integer
), and
[[RoundingMagnitude]]
(an
integer
).
It involves solving the following equation, which returns a valid
mathematical value
given
integer
inputs:
ToRawFixedFn(
) =
× 10
**(
It performs the following steps when called:
1.
Let
be
maxFraction
2.
Let
n1
be an
integer
and
r1
mathematical value
, with
r1
ToRawFixedFn
n1
, such that
n1
modulo
roundingIncrement
= 0
r1
, and
r1
is maximized.
3.
Let
n2
be an
integer
and
r2
mathematical value
, with
r2
ToRawFixedFn
n2
, such that
n2
modulo
roundingIncrement
= 0
r2
, and
r2
is minimized.
4.
Let
xFinal
be
ApplyUnsignedRoundingMode
r1
r2
unsignedRoundingMode
).
5.
If
xFinal
is
r1
, let
be
n1
. Otherwise, let
be
n2
6.
If
= 0, let
be
"0"
. Otherwise, let
be the String consisting of the digits of the decimal representation of
(in order, with no leading zeroes).
7.
If
≠ 0, then
a.
Let
be the length of
b.
If
, then
i.
Let
be the String value consisting of
+ 1 -
occurrences of the code unit 0x0030 (DIGIT ZERO).
ii.
Set
to the
string-concatenation
of
and
iii.
Set
to
+ 1.
c.
Let
be the first
code units of
, and let
be the remaining
code units of
d.
Set
to the
string-concatenation
of
"."
, and
e.
Let
int
be the length of
8.
Else,
a.
Let
int
be the length of
9.
Let
cut
be
maxFraction
minFraction
10.
Repeat, while
cut
> 0 and the last code unit of
is 0x0030 (DIGIT ZERO),
a.
Remove the last code unit from
b.
Set
cut
to
cut
- 1.
11.
If the last code unit of
is 0x002E (FULL STOP), then
a.
Remove the last code unit from
12.
Return the
Record
[[FormattedString]]
[[RoundedNumber]]
xFinal
[[IntegerDigitsCount]]
int
[[RoundingMagnitude]]
: –
}.
16.5.10
UnwrapNumberFormat (
nf
The abstract operation UnwrapNumberFormat takes argument
nf
(an
ECMAScript language value
) and returns either a
normal completion containing
an
ECMAScript language value
or a
throw completion
It returns the NumberFormat instance of its input object,
which is either the value itself or a value associated with it by
%Intl.NumberFormat%
according to the normative optional
constructor
mode of
4.3 Note 1
It performs the following steps when called:
1.
If
nf
is not an Object
, throw a
TypeError
exception.
2.
If
nf
does not have an
[[InitializedNumberFormat]]
internal slot and ?
OrdinaryHasInstance
%Intl.NumberFormat%
nf
) is
true
, then
a.
Return ?
Get
nf
%Intl%
[[FallbackSymbol]]
).
3.
Return
nf
16.5.11
GetNumberFormatPattern (
numberFormat
The abstract operation GetNumberFormatPattern takes arguments
numberFormat
(an Intl.NumberFormat) and
(an
Intl mathematical value
and returns a String.
It 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
16.2.3
It performs the following steps when called:
1.
Let
resolvedLocaleData
be
numberFormat
[[LocaleData]]
2.
Let
patterns
be
resolvedLocaleData
[[patterns]]
3.
Assert
patterns
is a
Record
(see
16.2.3
).
4.
Let
style
be
numberFormat
[[Style]]
5.
If
style
is
"percent"
, then
a.
Set
patterns
to
patterns
[[percent]]
6.
Else if
style
is
"unit"
, then
a.
Let
unit
be
numberFormat
[[Unit]]
b.
Let
unitDisplay
be
numberFormat
[[UnitDisplay]]
c.
Set
patterns
to
patterns
[[unit]]
d.
If
patterns
doesn't have a field [[<
unit
>]], then
i.
Set
unit
to
"fallback"
e.
Set
patterns
to
patterns
.[[<
unit
>]].
f.
Set
patterns
to
patterns
.[[<
unitDisplay
>]].
7.
Else if
style
is
"currency"
, then
a.
Let
currency
be
numberFormat
[[Currency]]
b.
Let
currencyDisplay
be
numberFormat
[[CurrencyDisplay]]
c.
Let
currencySign
be
numberFormat
[[CurrencySign]]
d.
Set
patterns
to
patterns
[[currency]]
e.
If
patterns
doesn't have a field [[<
currency
>]], then
i.
Set
currency
to
"fallback"
f.
Set
patterns
to
patterns
.[[<
currency
>]].
g.
Set
patterns
to
patterns
.[[<
currencyDisplay
>]].
h.
Set
patterns
to
patterns
.[[<
currencySign
>]].
8.
Else,
a.
Assert
style
is
"decimal"
b.
Set
patterns
to
patterns
[[decimal]]
9.
If
is
negative-infinity
, then
a.
Let
category
be
negative-non-zero
10.
Else if
is
negative-zero
, then
a.
Let
category
be
negative-zero
11.
Else if
is
not-a-number
, then
a.
Let
category
be
positive-zero
12.
Else if
is
positive-infinity
, then
a.
Let
category
be
positive-non-zero
13.
Else,
a.
Assert
is a
mathematical value
b.
If
< 0, then
i.
Let
category
be
negative-non-zero
c.
Else if
> 0, then
i.
Let
category
be
positive-non-zero
d.
Else,
i.
Let
category
be
positive-zero
14.
Let
signDisplay
be
numberFormat
[[SignDisplay]]
15.
If
signDisplay
is
"never"
, then
a.
Let
pattern
be
patterns
[[zeroPattern]]
16.
Else if
signDisplay
is
"auto"
, then
a.
If
category
is
positive-non-zero
or
positive-zero
, then
i.
Let
pattern
be
patterns
[[zeroPattern]]
b.
Else,
i.
Let
pattern
be
patterns
[[negativePattern]]
17.
Else if
signDisplay
is
"always"
, then
a.
If
category
is
positive-non-zero
or
positive-zero
, then
i.
Let
pattern
be
patterns
[[positivePattern]]
b.
Else,
i.
Let
pattern
be
patterns
[[negativePattern]]
18.
Else if
signDisplay
is
"exceptZero"
, then
a.
If
category
is
positive-zero
or
negative-zero
, then
i.
Let
pattern
be
patterns
[[zeroPattern]]
b.
Else if
category
is
positive-non-zero
, then
i.
Let
pattern
be
patterns
[[positivePattern]]
c.
Else,
i.
Let
pattern
be
patterns
[[negativePattern]]
19.
Else,
a.
Assert
signDisplay
is
"negative"
b.
If
category
is
negative-non-zero
, then
i.
Let
pattern
be
patterns
[[negativePattern]]
c.
Else,
i.
Let
pattern
be
patterns
[[zeroPattern]]
20.
Return
pattern
16.5.12
GetNotationSubPattern (
numberFormat
exponent
The abstract operation GetNotationSubPattern takes arguments
numberFormat
(an Intl.NumberFormat) and
exponent
(an
integer
) and returns a String.
It considers the resolved notation and
exponent
, and returns a String value for the notation sub pattern as described in
16.2.3
It performs the following steps when called:
1.
Let
resolvedLocaleData
be
numberFormat
[[LocaleData]]
2.
Let
notationSubPatterns
be
resolvedLocaleData
[[notationSubPatterns]]
3.
Assert
notationSubPatterns
is a
Record
(see
16.2.3
).
4.
Let
notation
be
numberFormat
[[Notation]]
5.
If
notation
is
"scientific"
or
notation
is
"engineering"
, then
a.
Return
notationSubPatterns
[[scientific]]
6.
Else if
exponent
is not 0, then
a.
Assert
notation
is
"compact"
b.
Let
compactDisplay
be
numberFormat
[[CompactDisplay]]
c.
Let
compactPatterns
be
notationSubPatterns
[[compact]]
.[[<
compactDisplay
>]].
d.
Return
compactPatterns
.[[<
exponent
>]].
7.
Else,
a.
Return
"{number}"
16.5.13
ComputeExponent (
numberFormat
The abstract operation ComputeExponent takes arguments
numberFormat
(an Intl.NumberFormat) and
(a
mathematical value
) and returns an
integer
It computes an exponent (power of ten) by which to scale
according to the number formatting settings.
It handles cases such as 999 rounding up to 1000, requiring a different exponent.
It performs the following steps when called:
1.
If
= 0, then
a.
Return 0.
2.
If
< 0, then
a.
Let
= -
3.
Let
magnitude
be the base 10 logarithm of
rounded down to the nearest
integer
4.
Let
exponent
be
ComputeExponentForMagnitude
numberFormat
magnitude
).
5.
Let
be
× 10
**
exponent
6.
Let
formatNumberResult
be
FormatNumericToString
numberFormat
).
7.
If
formatNumberResult
[[RoundedNumber]]
= 0, then
a.
Return
exponent
8.
Let
newMagnitude
be the base 10 logarithm of
formatNumberResult
[[RoundedNumber]]
rounded down to the nearest
integer
9.
If
newMagnitude
is
magnitude
exponent
, then
a.
Return
exponent
10.
Return
ComputeExponentForMagnitude
numberFormat
magnitude
+ 1).
16.5.14
ComputeExponentForMagnitude (
numberFormat
magnitude
The abstract operation ComputeExponentForMagnitude takes arguments
numberFormat
(an Intl.NumberFormat) and
magnitude
(an
integer
) and returns an
integer
It 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).
It performs the following steps when called:
1.
Let
notation
be
numberFormat
[[Notation]]
2.
If
notation
is
"standard"
, then
a.
Return 0.
3.
Else if
notation
is
"scientific"
, then
a.
Return
magnitude
4.
Else if
notation
is
"engineering"
, then
a.
Let
thousands
be the greatest
integer
that is not greater than
magnitude
/ 3.
b.
Return
thousands
× 3.
5.
Else,
a.
Assert
notation
is
"compact"
b.
Let
exponent
be an
ILD
integer
by which to scale a number of the given magnitude in compact notation for the current locale.
c.
Return
exponent
16.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
12.9.3
), but some of the details are different.
It is defined piecewise over the following productions:
StringNumericLiteral
:::
StrWhiteSpace
opt
1.
Return 0.
StringNumericLiteral
:::
StrWhiteSpace
opt
StrNumericLiteral
StrWhiteSpace
opt
1.
Return
StringIntlMV
of
StrNumericLiteral
StrNumericLiteral
:::
NonDecimalIntegerLiteral
1.
Return MV of
NonDecimalIntegerLiteral
StrDecimalLiteral
:::
StrUnsignedDecimalLiteral
1.
Let
be
StringIntlMV
of
StrUnsignedDecimalLiteral
2.
If
is 0, return
negative-zero
3.
If
is
positive-infinity
, return
negative-infinity
4.
Return -
StrUnsignedDecimalLiteral
:::
Infinity
1.
Return
positive-infinity
StrUnsignedDecimalLiteral
:::
DecimalDigits
DecimalDigits
opt
ExponentPart
opt
1.
Let
be MV of the first
DecimalDigits
2.
If the second
DecimalDigits
is present, then
a.
Let
be MV of the second
DecimalDigits
b.
Let
be the number of code points in the second
DecimalDigits
3.
Else,
a.
Let
be 0.
b.
Let
be 0.
4.
If
ExponentPart
is present, let
be MV of
ExponentPart
. Otherwise, let
be 0.
5.
Return (
+ (
× 10
**
)) × 10
**
StrUnsignedDecimalLiteral
:::
DecimalDigits
ExponentPart
opt
1.
Let
be MV of
DecimalDigits
2.
If
ExponentPart
is present, let
be MV of
ExponentPart
. Otherwise, let
be 0.
3.
Let
be the number of code points in
DecimalDigits
4.
Return
× 10
**(
StrUnsignedDecimalLiteral
:::
DecimalDigits
ExponentPart
opt
1.
Let
be MV of
DecimalDigits
2.
If
ExponentPart
is present, let
be MV of
ExponentPart
. Otherwise, let
be 0.
3.
Return
× 10
**
16.5.16
ToIntlMathematicalValue (
value
The abstract operation ToIntlMathematicalValue takes argument
value
(an
ECMAScript language value
) and returns either a
normal completion containing
an
Intl mathematical value
or a
throw completion
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
7.1.3
, but a
mathematical value
can be returned instead of a Number or BigInt, so that exact decimal values can be represented.
It performs the following steps when called:
1.
Let
primValue
be ?
ToPrimitive
value
number
).
2.
If
primValue
is a BigInt
, return
primValue
).
3.
If
primValue
is a String
, then
a.
Let
str
be
primValue
4.
Else,
a.
Let
be ?
ToNumber
primValue
).
b.
If
is
-0
, return
negative-zero
c.
Let
str
be
Number::toString
, 10).
5.
Let
text
be
StringToCodePoints
str
).
6.
Let
literal
be
ParseText
text
StringNumericLiteral
).
7.
If
literal
is a
List
of errors, return
not-a-number
8.
Let
intlMV
be the
StringIntlMV
of
literal
9.
If
intlMV
is a
mathematical value
, then
a.
Let
rounded
be
RoundMVResult
abs
intlMV
)).
b.
If
rounded
is
+∞
and
intlMV
< 0, return
negative-infinity
c.
If
rounded
is
+∞
, return
positive-infinity
d.
If
rounded
is
+0
and
intlMV
< 0, return
negative-zero
e.
If
rounded
is
+0
, return 0.
10.
Return
intlMV
16.5.17
GetUnsignedRoundingMode (
roundingMode
sign
The abstract operation GetUnsignedRoundingMode takes arguments
roundingMode
(a
rounding mode
) and
sign
negative
or
positive
) and returns a specification type from the Unsigned Rounding Mode column of
Table 29
. It returns the
rounding mode
that should be applied to the absolute value of a number to produce the same result as if
roundingMode
were applied to the signed value of the number (negative if
sign
is
negative
, or positive otherwise). It performs the following steps when called:
1.
Return the specification type in the Unsigned Rounding Mode column of
Table 29
for the row where the value in the Identifier column is
roundingMode
and the value in the Sign column is
sign
Table 29: Conversion from
rounding mode
to unsigned
rounding mode
Identifier
Sign
Unsigned Rounding Mode
"ceil"
positive
infinity
negative
zero
"floor"
positive
zero
negative
infinity
"expand"
positive
infinity
negative
infinity
"trunc"
positive
zero
negative
zero
"halfCeil"
positive
half-infinity
negative
half-zero
"halfFloor"
positive
half-zero
negative
half-infinity
"halfExpand"
positive
half-infinity
negative
half-infinity
"halfTrunc"
positive
half-zero
negative
half-zero
"halfEven"
positive
half-even
negative
half-even
16.5.18
ApplyUnsignedRoundingMode (
r1
r2
unsignedRoundingMode
The abstract operation ApplyUnsignedRoundingMode takes arguments
(a
mathematical value
),
r1
(a
mathematical value
),
r2
(a
mathematical value
), and
unsignedRoundingMode
(a specification type from the Unsigned Rounding Mode column of
Table 29
, or
undefined
) and returns a
mathematical value
. It considers
, bracketed below by
r1
and above by
r2
, and returns either
r1
or
r2
according to
unsignedRoundingMode
. It performs the following steps when called:
1.
If
is
r1
, return
r1
2.
Assert
r1
r2
3.
Assert
unsignedRoundingMode
is not
undefined
4.
If
unsignedRoundingMode
is
zero
, return
r1
5.
If
unsignedRoundingMode
is
infinity
, return
r2
6.
Let
d1
be
r1
7.
Let
d2
be
r2
8.
If
d1
d2
, return
r1
9.
If
d2
d1
, return
r2
10.
Assert
d1
is
d2
11.
If
unsignedRoundingMode
is
half-zero
, return
r1
12.
If
unsignedRoundingMode
is
half-infinity
, return
r2
13.
Assert
unsignedRoundingMode
is
half-even
14.
Let
cardinality
be
r1
/ (
r2
r1
))
modulo
15.
If
cardinality
is 0, return
r1
16.
Return
r2
16.5.19
PartitionNumberRangePattern (
numberFormat
The abstract operation PartitionNumberRangePattern takes arguments
numberFormat
(an Intl.NumberFormat),
(an
Intl mathematical value
), and
(an
Intl mathematical value
) and returns either a
normal completion containing
List
of
Records
with fields
[[Type]]
(a String),
[[Value]]
(a String), and
[[Source]]
(a String), or a
throw completion
. It creates the parts for a localized number range according to
, and the formatting options of
numberFormat
. It performs the following steps when called:
1.
If
is
not-a-number
or
is
not-a-number
, throw a
RangeError
exception.
2.
Let
xResult
be
PartitionNumberPattern
numberFormat
).
3.
Let
yResult
be
PartitionNumberPattern
numberFormat
).
4.
If
FormatNumeric
numberFormat
) is
FormatNumeric
numberFormat
), then
a.
Let
appxResult
be
FormatApproximately
numberFormat
xResult
).
b.
For each element
of
appxResult
, do
i.
Set
[[Source]]
to
"shared"
c.
Return
appxResult
5.
Let
result
be a new empty
List
6.
For each element
of
xResult
, do
a.
Append the
Record
[[Type]]
[[Type]]
[[Value]]
[[Value]]
[[Source]]
"startRange"
} to
result
7.
Let
rangeSeparator
be an
ILND
String value used to separate two numbers.
8.
Append the
Record
[[Type]]
"literal"
[[Value]]
rangeSeparator
[[Source]]
"shared"
} to
result
9.
For each element
of
yResult
, do
a.
Append the
Record
[[Type]]
[[Type]]
[[Value]]
[[Value]]
[[Source]]
"endRange"
} to
result
10.
Return
CollapseNumberRange
numberFormat
result
).
16.5.20
FormatApproximately (
numberFormat
result
The abstract operation FormatApproximately takes arguments
numberFormat
(an Intl.NumberFormat) and
result
(a
List
of
Records
with fields
[[Type]]
(a String) and
[[Value]]
(a String)) and returns a
List
of
Records
with fields
[[Type]]
(a String) and
[[Value]]
(a String). It 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
. It performs the following steps when called:
1.
Let
approximatelySign
be an
ILND
String value used to signify that a number is approximate.
2.
If
approximatelySign
is not empty, insert the
Record
[[Type]]
"approximatelySign"
[[Value]]
approximatelySign
} at an
ILND
index in
result
. For example, if
numberFormat
has
[[Locale]]
"en-US"
and
[[NumberingSystem]]
"latn"
and
[[Style]]
"decimal"
, the new
Record
might be inserted before the first element of
result
3.
Return
result
16.5.21
CollapseNumberRange (
numberFormat
result
The
implementation-defined
abstract operation CollapseNumberRange takes arguments
numberFormat
(an Intl.NumberFormat) and
result
(a
List
of
Records
with fields
[[Type]]
(a String),
[[Value]]
(a String), and
[[Source]]
(a String)) and returns a
List
of
Records
with fields
[[Type]]
(a String),
[[Value]]
(a String), and
[[Source]]
(a String). It modifies
result
(which must be a
List
of
Records
as constructed within
PartitionNumberRangePattern
) according to the effective locale and the formatting options of
numberFormat
by removing redundant information, resolving internal inconsistency,
replacing characters when necessary, and inserting spacing when
necessary. It then returns the resulting
List
. The algorithm is
ILND
, but must not introduce ambiguity that would cause the result of
Intl.NumberFormat.prototype.formatRange (
start
end
with arguments
List
start1
end1
» to equal the result with arguments
List
start2
end2
» if the results for those same arguments
Lists
would not be equal with a trivial implementation of CollapseNumberRange that always returns
result
unmodified.
For example, an implementation may remove the
Record
representing a currency symbol after a range separator to convert a
results
List
representing
"$3–$5"
into one representing
"$3–5"
An implementation may also modify
Record
[[Value]]
fields for grammatical correctness; for example, converting a
results
List
representing
"0.5 miles–1 mile"
into one representing
"0.5–1 miles"
Returning
result
unmodified is guaranteed to be a correct implementation of CollapseNumberRange.
16.5.22
FormatNumericRange (
numberFormat
The abstract operation FormatNumericRange takes arguments
numberFormat
(an Intl.NumberFormat),
(an
Intl mathematical value
), and
(an
Intl mathematical value
) and returns either a
normal completion containing
a String or a
throw completion
. It performs the following steps when called:
1.
Let
parts
be ?
PartitionNumberRangePattern
numberFormat
).
2.
Let
result
be the empty String.
3.
For each element
part
of
parts
, do
a.
Set
result
to the
string-concatenation
of
result
and
part
[[Value]]
4.
Return
result
16.5.23
FormatNumericRangeToParts (
numberFormat
The abstract operation FormatNumericRangeToParts takes arguments
numberFormat
(an Intl.NumberFormat),
(an
Intl mathematical value
), and
(an
Intl mathematical value
) and returns either a
normal completion containing
an Array or a
throw completion
. It performs the following steps when called:
1.
Let
parts
be ?
PartitionNumberRangePattern
numberFormat
).
2.
Let
result
be !
ArrayCreate
(0).
3.
Let
be 0.
4.
For each element
part
of
parts
, do
a.
Let
be
OrdinaryObjectCreate
%Object.prototype%
).
b.
Perform !
CreateDataPropertyOrThrow
"type"
part
[[Type]]
).
c.
Perform !
CreateDataPropertyOrThrow
"value"
part
[[Value]]
).
d.
Perform !
CreateDataPropertyOrThrow
"source"
part
[[Source]]
).
e.
Perform !
CreateDataPropertyOrThrow
result
, !
ToString
)),
).
f.
Increment
by 1.
5.
Return
result