Stage 1 Draft / December 11, 2024

Decimal

Introduction

This specification consists of two parts:

1 The Decimal128 Object

Introduction

Decimal128 values, as specified here, are intended to represent base-10 (decimal) numbers as specified in IEEE 754-2019 Decimal128. All values specified in IEEE 754-2019 Decimal128 are modeled here, though mathematically equal members of a cohort (intuitively, IEEE 754-2019 Decimal128 values that differ only in the number of trailing zeroes after the decimal point) are indistinguishable here.

A Decimal128 value, as specified here, is one of the following six kinds of values:

  • NaN𝔻, represending a decimal not-a-number
  • +∞𝔻, representing positive infinity as a decimal,
  • -∞𝔻, representing negative infinity as a decimal,
  • +0𝔻, represending non-negative zero as a decimal value
  • −0𝔻, representing negative zero as a decimal value, or
  • a mathematical value v for which there exists an integer q satisfing the following conditions:
    • -6176 ≤ q ≤ 6111,
    • v × 10q is an integer n such that 0 < abs(n) < 1034
Note 1

A Decimal128 value is said to be finite if it is either a mathematical value, +0𝔻 or -0𝔻. A zero Decimal128 value is one of +0𝔻 or -0𝔻. A finite non-zero Decimal128 value is a mathematical value satisfying the conditions listed above.

The mathematical value MV(x) of a finite Decimal128 value x is defined as follows:

  • MV(+0𝔻) = 0
  • MV(-0𝔻) = 0
  • MV(v) = v (provided v is neither +0𝔻 nor -0𝔻)

Decimal128 values defined in this section are ECMAScript analogues of IEEE 754-2019 Decimal128 values. It is important to note that the full spectrum of values defined by IEEE 754-2019 Decimal128 are not available here, namely non-canonical Decimal128 values, which can be understood as values containing trailing zeroes. Also, this specification simplifies IEEE 754-2019 Decimal128 in a further way: there is only one Decimal128 value, NaN𝔻, representing all possible IEEE 754-2019 Decimal128 NaN values.

A Decimal128 rounding mode is one of the String values "ceil", "floor", "trunc", "halfExpand", and "halfEven". The default rounding mode is the String value "halfEven".

Table 1: Rounding modes in Decimal128 compared to IEEE 754-2019 rounding modes
Decimal128 rounding mode Description IEEE 754-2019 rounding mode
"ceil" Toward positive infinity "roundTowardPositive"
"floor" Toward negative infinity "roundTowardNegative"
"trunc" Toward zero "roundTowardZero"
"halfExpand" Ties away from zero "roundTiesToAway"
"halfEven" Ties toward an even rounding increment multiple "roundTiesToEven"
Note 2
The above five rounding modes are defined in IEEE 754-2019. This table is offered for implementors who may need to convert the Decimal128 rounding modes defined here into a library that may use the official IEEE 754-2019 rounding mode names. Additional rounding modes are used elsewhere in this specification, such as in Intl.NumberFormat.

For every non-NaN Decimal128 value, we define its sign as follows:

  • sign(+∞𝔻) = 1
  • sign(-∞𝔻) = -1
  • sign(+0𝔻) = 1
  • sign(−0𝔻) = -1
  • sign(v) = v / abs(v) for all other Decimal128 values v

For every finite non-zero Decimal128 value v there exists a unique integer e and mathematical value s such that

  1. v = s × 10e
  2. 1 ≤ abs(s) < 10

We call e the exponent and s the significand of v. The exponent and significand are undefined for NaN, non-finite, and zero Decimal128 values.

Note 3

The significand of a finite non-zero Decimal128 value is a rational number.

Note 4

The exponent e of finite non-zero Decimal128 values is an integer satisfying 6144 ≥ e ≥ -6176.

A finite non-zero Decimal128 value is normalized if its exponent e satisfies 6144 ≥ e ≥ -6143. A finite non-zero Decimal128 value is denormalized if its exponent e satisfies -6144 ≥ e ≥ -6176.

For a proper discussion of rounding, we need to separate how rounding occurs with normalized compared with denormlized values. For a normalized Decimal128 value we define its truncated exponent as equal to its exponent. For zero or denormalized Decimal128 values we define the truncated exponent as the constant -6143. Given this, we define the scaled significand of a finite Decimal128 value as follows:

Note 5

The scaled significand of a finite Decimal128 value is always an integer whose absolute value is less than 1034.

1.1 Abstract Operations

1.1.1 RoundToDecimal128Domain ( v [ , roundingMode ] )

The abstract operation RoundToDecimal128Domain takes argument v (a mathematical value) and optional argument roundingMode (a Decimal128 rounding mode) and returns +∞𝔻, -∞𝔻, +0𝔻, −0𝔻, or a mathematical value. It computes the closest approximation to a given mathematical value, rounded according to the given rounding mode, that is available within the limits of Decimal128. It performs the following steps when called:

  1. If v = 0, return +0𝔻.
  2. If v < 0, then
    1. Let reverseRoundingMode be roundingMode.
    2. If roundingMode is "floor", set reverseRoundingMode to "ceil".
    3. If roundingMode is "ceil", set reverseRoundingMode to "floor".
    4. Let d be RoundToDecimal128Domain(–v, reverseRoundingMode).
    5. If d is +∞𝔻, return –∞𝔻.
    6. If d is +0𝔻, return −0𝔻.
    7. Assert: d is a mathematical value.
    8. Return –d.
  3. Let e be the unique integer such that 10ev < 10e+1.
  4. Let te be e − 33.
  5. If te < –6176, set te to –6176.
  6. Let m be v × 10te.
  7. Let rounded be ApplyRoundingModeToPositive(m, roundingMode).
  8. If rounded = 1034, then
    1. Set te to te + 1.
    2. Set rounded to 1033.
  9. If te > 6111, return +∞𝔻.
  10. If rounded = 0, return +0𝔻.
  11. Return rounded × 10te.

1.1.1.1 ApplyRoundingModeToPositive ( m, roundingMode )

The abstract operation ApplyRoundingModeToPositive takes arguments m (a positive mathematical value) and roundingMode (a Decimal128 rounding mode) and returns an integer. It computes the closest integer approximation to a given positive mathematical value, rounded according to the given rounding mode. It performs the following steps when called:

  1. Let mLow be floor(m).
  2. Let fraction be mmLow.
  3. If fraction = 0, return mLow.
  4. Let mHigh be mLow + 1.
  5. If roundingMode is "floor" or "trunc", return mLow.
  6. If roundingMode is "ceil", return mHigh.
  7. If fraction < 0.5, return mLow.
  8. If fraction > 0.5, return mHigh.
  9. If roundingMode is "halfExpand", return mHigh.
  10. If mLow is an even integer, return mLow.
  11. Return mHigh.

1.1.2 Decimal128Abs ( argument )

The abstract operation Decimal128Abs takes argument argument (a Decimal128 value) and returns a Decimal128 value. It computes the absolute value of a Decimal128 value It performs the following steps when called:

  1. If argument is NaN𝔻, return NaN𝔻.
  2. If argument is +∞𝔻 or -∞𝔻, return +∞𝔻.
  3. If argument is +0𝔻 or −0𝔻, return +0𝔻.
  4. Otherwise, return abs(argument).

1.1.3 Decimal128Negate ( argument )

The abstract operation Decimal128Negate takes argument argument (a Decimal128 value) and returns a Decimal128 value. It computes the negation of a Decimal128 value It performs the following steps when called:

  1. If argument is NaN𝔻, return NaN𝔻.
  2. If argument is +∞𝔻, return -∞𝔻.
  3. If argument is -∞𝔻, return +∞𝔻.
  4. If argument is +0𝔻, return −0𝔻.
  5. If argument is −0𝔻, return +0𝔻.
  6. Otherwise, return −argument.

1.1.4 CanonicalizeDecimalString ( digits )

The abstract operation CanonicalizeDecimalString takes argument digits (a String) and returns a String. It removes trailing zeroes, if any, from digits, which is assumed to be a string of digits, possibily followed by a "." and a non-empty sequence of digits. It performs the following steps when called:

  1. If digits does not contain the substring ".", return digits.
  2. If the final code unit of digits is not the code unit 0x0030 (DIGIT ZERO), return digits.
  3. Let lhs be the substring of digits up to the first occurrence of the string ".".
  4. Let rhs be the substring of digits starting at the first code point after the first occurrence of the string ".".
  5. Let noTrailingZeroes be the longest substring of rhs that does not terminate with a sequence of the code point 0x0030 (DIGIT ZERO).
  6. If noTrailingZeroes is "", return lhs.
  7. Otherwise, return the concatenation of lhs, ".", and noTrailingZeroes.

1.1.5 Decimal128ToDecimalString ( argument )

The abstract operation Decimal128ToDecimalString takes argument argument (a Decimal128 value) and returns a String. It renders argument as a string in decimal notation, regardless of how many decimal digits would be required. It performs the following steps when called:

  1. If argument is NaN𝔻, return "NaN".
  2. If argument is +∞𝔻, return "Infinity".
  3. If argument is -∞𝔻, return "-Infinity".
  4. Let sign be sign(argument).
  5. If sign = -1, let prefix be "-", else let prefix be "".
  6. Let argument be Decimal128Abs(argument).
  7. If argument is +0𝔻, return the string concatenation of prefix and "0".
  8. Let q be the largest integer such that argument × 10q is an integer.
  9. Let n be argument × 10q.
  10. Let x be floor(argument).
  11. Let y be argument mod 1.
  12. Assert: 0 < n < 1034.
  13. Let digits be the unique decimal string representation of x without leading zeroes.
  14. If y = 0, let fractionalPart be "", else let fractionalPart be the unique decimal string representation of y without leading zeroes.
  15. Let numDigits be the length of digits.
  16. Let integerPart be the substring of digits from 0 to numDigits.
  17. If argument is an integer, then
    1. Assert: integerPart is not "".
    2. Return integerPart.
  18. If integerPart is "", set integerPart to "0".
  19. Let nonIntegerPart be the substring of fractionalPart from 0 to numDigits.
  20. Let renderedAbsoluteValue be the concatenation of integerPart, ".", and nonIntegerPart.
  21. Let s be the concatenation of prefix and renderedAbsoluteValue.
  22. Return CanonicalizeDecimalString(s).

1.1.6 Decimal128ToExponentialString ( argument )

The abstract operation Decimal128ToExponentialString takes argument argument (a Decimal128 value) and returns a String. It renders argument in exponential notation. It performs the following steps when called:

  1. If argument is NaN𝔻, return "NaN".
  2. If argument is +∞𝔻, return "Infinity".
  3. If argument is -∞𝔻, return "-Infinity".
  4. Let sign be sign(argument).
  5. Let argument be Decimal128Abs(argument).
  6. If sign = -1, let prefix be "-", else let prefix be "".
  7. If argument is +0𝔻 or −0𝔻, return the string concatenation of prefix and *"0e+0".
  8. Let e be the unique integer for which 1 ≤ argument × 10e < 10.
  9. Let mantissa be argument / 10e.
  10. Let coefficientStr be Decimal128ToDecimalString(mantissa).
  11. Let exponentStr be the unique decimal string representation of e without leading zeroes.
  12. Return the concatenation of prefix, coefficientStr, "e", and exponentStr.

1.1.7 Decimal128ValueToObject ( argument )

The abstract operation Decimal128ValueToObject takes argument argument (a Decimal128 value) and returns a Decimal128 object. It converts a Decimal128 value to a Decimal128 object. It performs the following steps when called:

  1. Let O be ! OrdinaryCreateFromConstructor(%Decimal128%, "%Decimal128.prototype%", « [[Decimal128Data]] »).
  2. Set O.[[Decimal128Data]] to argument.
  3. Return O.

1.2 The Decimal128 Constructor

The Decimal128 constructor:

  • is %Decimal128%.
  • is the initial value of the the "Decimal128" property of the global object.
  • creates and initializes a new Decimal128 object when called as a constructor
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Decimal128 behaviour must include a super call to the Decimal128 constructor to create and initialize the subclass instance with a [[Decimal128Data]] internal slot.

1.2.1 Decimal128 ( x )

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let toParse be undefined.
  3. If x is a BigInt, set toParse to BigInt::toString(x, 10).
  4. Otherwise, if x is a Number, set toParse to ! Call(%Number.prototype.toExponential%, x, « »).
  5. Otherwise, if x is a String, set toParse to x.
  6. If toParse is not a String, throw a TypeError exception.
  7. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%Decimal128.prototype%", « [[Decimal128Data]] »).
  8. If toParse is "NaN", then
    1. Set O.[[Decimal128Data]] to NaN𝔻.
  9. Else,
    1. Let parseResult be ParseText(toParse, StrDecimalLiteral).
    2. If parseResult is a List of errors, throw a SyntaxError exception.
    3. Let decimalValue be ? StringDecimalValue of parseResult.
    4. Set O.[[Decimal128Data]] to decimalValue.
  10. Return O.
Note

Given a Number argument, the constructor converts it to a String using the toString method (with no arguments). In some cases, this may not be desired. In some use cases, given a Number, one may wish to call the Decimal128 constructor not with the number but rather with, for instance, the result of calling toFixed or toPrecision on the Number, thereby ensuring a certain level of precision that may get lost when using Number’s toString.

1.2.1.1 Runtime Semantics: StringDecimalValue

The syntax-directed operation StringDecimalValue takes no arguments and returns either a normal completion containing a Decimal128 value or a throw completion. It is defined piecewise over the following productions:

StrDecimalLiteral ::: - StrUnsignedDecimalLiteral
  1. Let a be ? StringDecimalValue of StrUnsignedDecimalLiteral.
  2. If a is +∞𝔻, return -∞𝔻.
  3. Assert: a is finite.
  4. If a is +0𝔻, return −0𝔻.
  5. Return −a.
StrUnsignedDecimalLiteral ::: Infinity
  1. Return +∞𝔻.
StrUnsignedDecimalLiteral ::: DecimalDigits . DecimalDigitsopt ExponentPartopt
  1. Let a be MV of the first DecimalDigits.
  2. If the second DecimalDigits is present, then
    1. Let b be MV of the second DecimalDigits.
    2. Let n be the number of code points in the second DecimalDigits.
  3. Else,
    1. Let b be 0.
    2. Let n be 0.
  4. If ExponentPart is present, let e be MV of ExponentPart. Otherwise, let e be 0.
  5. Return RoundToDecimal128Domain((a + (b × 10n)) × 10e).
StrUnsignedDecimalLiteral ::: . DecimalDigits ExponentPartopt
  1. Let b be MV of DecimalDigits.
  2. If ExponentPart is present, let e be MV of ExponentPart. Otherwise, let e be 0.
  3. Let n be the number of code points in DecimalDigits.
  4. Let newValue be b × 10en.
  5. Return RoundToDecimal128Domain(newValue).
StrUnsignedDecimalLiteral ::: DecimalDigits ExponentPartopt
  1. Let a be MV of DecimalDigits.
  2. If ExponentPart is present, let e be MV of ExponentPart. Otherwise, let e be 0.
  3. Return RoundToDecimal128Domain(a × 10e).

2 Properties of the Decimal128 Prototype

2.1 Decimal128.prototype.isNaN ( )

This method returns a Boolean value indicating whether a Decimal128 object represents NaN𝔻.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Let d be O.[[Decimal128Data]].
  4. If d is NaN𝔻, return true.
  5. Otherwise, return false.

2.2 Decimal128.prototype.isFinite ( )

This method returns a Boolean value indicating whether a Decimal128 object represents +∞𝔻 or -∞𝔻.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Let d be O.[[Decimal128Data]].
  4. If d is NaN𝔻, +∞𝔻 or -∞𝔻, return false.
  5. Otherwise, return true.

2.3 Decimal128.prototype.exponent ( )

This method returns a Number value represents the exponent, which is the integer n for which the current Decimal128 object, v, there exists a mathematical value s such that v = s × 10e and 1 ≤ abs(s) < 10. If the current Decimal128 object is infinite, it returns +∞. If the current Decimal128 object is a zero, it returns -∞.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Let d be O.[[Decimal128Data]].
  4. If d is NaN𝔻, return NaN𝔽.
  5. If d is +∞𝔻 or -∞𝔻, return +∞𝔽.
  6. If d is +0𝔻 or −0𝔻, return -∞𝔽.
  7. Let e be the unique integer for which there exists a mathematical value s such that d = s × 10e and 1 ≤ abs(s) < 10.
  8. Return 𝔽(e).

2.4 Decimal128.prototype.mantissa ( )

This method returns a Decimal128 value representing the significand of the current Decimal128 object, which is the mathematical value s for which the current Decimal128 object, v, there exists an integer e such such that v = s × 10e and 1 ≤ abs(s) < 10. If the current Decimal128 object is a zero, it returns a zero.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Let d be O.[[Decimal128Data]].
  4. If d is NaN𝔻, return Decimal128ValueToObject(NaN𝔽).
  5. If d is +∞𝔻 or -∞𝔻, return Decimal128ValueToObject(+∞𝔽).
  6. If d is +0𝔻, return Decimal128ValueToObject(+0𝔻).
  7. If d is −0𝔻, return Decimal128ValueToObject(-0𝔻).
  8. Let s be the unique mathematical value such that d = s × 10e and 1 ≤ abs(s) < 10.
  9. Return Decimal128ValueToObject(s).

2.5 Decimal128.prototype.abs ( )

This method computes the absolute value of a Decimal128 object.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Let d be O.[[Decimal128Data]].
  4. Return Decimal128ValueToObject(Decimal128Abs(d)).
Note

This operation follows the specification in Section 5.5.1 of IEEE 754-2019.

2.6 Decimal128.prototype.negate ( )

This method inverts the sign of a Decimal128 object.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Let d be O.[[Decimal128Data]].
  4. Return Decimal128ValueToObject(Decimal128Negate(d)).
Note

This operation follows the specification in Section 5.5.1 of IEEE 754-2019.

2.7 Decimal128.prototype.add ( x )

This method computes the addition of a Decimal128 object with another one. The computation proceeds as though infinite precision and unbounded range were available, rounding, if necessary.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 or d2 is NaN𝔻, return Decimal128ValueToObject(NaN𝔻).
  7. If d1 is +∞𝔻 or d2 is +∞𝔻, then
    1. If d1 is -∞𝔻 or d2 is -∞𝔻, return Decimal128ValueToObject(NaN𝔻).
    2. Return Decimal128ValueToObject(+∞𝔻).
  8. If d1 is -∞𝔻 or d2 is -∞𝔻, then
    1. Assert: d1 is not +∞𝔻 and d2 is not +∞𝔻.
    2. Return Decimal128ValueToObject(-∞𝔻).
  9. If d1 is −0𝔻, return Decimal128ValueToObject(d2).
  10. If d2 is −0𝔻, return Decimal128ValueToObject(d1).
  11. If d1 is +0𝔻, set d1 to 0.
  12. If d2 is +0𝔻, set d2 to 0.
  13. Let sum be d1 + d2.
  14. Return Decimal128ValueToObject(RoundToDecimal128Domain(sum)).
Note

This operation follows the specification in Section 5.4.1 of IEEE 754-2019.

2.8 Decimal128.prototype.subtract ( x )

This method computes subtracts the given Decimal128 object from the current one. The computation proceeds as though infinite precision and unbounded range were available, rounding, if necessary.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 or d2 is NaN𝔻, return Decimal128ValueToObject(NaN𝔻).
  7. If d1 is +∞𝔻 or -∞𝔻, then
    1. If d2 is d1, return Decimal128ValueToObject(NaN𝔻).
    2. Return Decimal128ValueToObject(d1).
  8. If d2 is +∞𝔻, return Decimal128ValueToObject(-∞𝔻).
  9. If d2 is -∞𝔻, return Decimal128ValueToObject(+∞𝔻).
  10. If d1 is −0𝔻 and d2 is +0𝔻, return Decimal128ValueToObject((−0𝔻)).
  11. If d1 is +0𝔻 or −0𝔻, set d1 to 0.
  12. If d2 is +0𝔻 or −0𝔻, set d2 to 0.
  13. Let difference be d1d2.
  14. Return Decimal128ValueToObject(RoundToDecimal128Domain(difference)).
Note

This operation follows the specification in Section 5.4.1 of IEEE 754-2019.

2.9 Decimal128.prototype.multiply ( x )

This method computes multiplies the current Decimal128 object by another one. The computation proceeds as though infinite precision and unbounded range were available, rounding, if necessary.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 or d2 is NaN𝔻, return Decimal128ValueToObject(NaN𝔻).
  7. If d1 or d2 is +∞𝔻, then
    1. If d1 or d2 is a zero Decimal128 value, return Decimal128ValueToObject(NaN𝔻).
    2. If sign(d1) = -1 or sign(d2) = -1, return Decimal128ValueToObject(-∞𝔻).
    3. Return Decimal128ValueToObject(+∞𝔻).
  8. If d1 or d2 is -∞𝔻, then
    1. If d1 or d2 is a zero Decimal128 value, return Decimal128ValueToObject(NaN𝔻).
    2. If sign(d1) = -1 and sign(d2) = -1, return Decimal128ValueToObject(+∞𝔻).
    3. Return Decimal128ValueToObject(-∞𝔻).
  9. If d1 or d2 is +0𝔻, then
    1. If sign(d1) = -1 or sign(d2) = -1, return Decimal128ValueToObject(−0𝔻).
    2. Return Decimal128ValueToObject(+0𝔻).
  10. If d1 or d2 is −0𝔻, then
    1. If sign(d1) = -1 and sign(d2) = -1, return Decimal128ValueToObject(+0𝔻_).
    2. Return Decimal128ValueToObject(−0𝔻).
  11. Let product be d1 × d2.
  12. Assert: product ≠ 0.
  13. Return Decimal128ValueToObject(RoundToDecimal128Domain(product)).
Note

This operation follows the specification in Section 5.4.1 of IEEE 754-2019.

2.10 Decimal128.prototype.divide ( x )

This method computes divides the current Decimal128 object by another one. The computation proceeds as though infinite precision and unbounded range were available, rounding, if necessary.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 or d2 is NaN𝔻, return Decimal128ValueToObject(NaN𝔻).
  7. If d1 is +∞𝔻, then
    1. If d2 is +∞𝔻 or -∞𝔻, return Decimal128ValueToObject(NaN𝔻).
    2. If sign(d2) = -1, return Decimal128ValueToObject(-∞𝔻).
    3. Otherwise, return Decimal128ValueToObject(+∞𝔻).
  8. If d1 is -∞𝔻, then
    1. If d2 is +∞𝔻 or -∞𝔻, return Decimal128ValueToObject(NaN𝔻).
    2. If sign(d2) = -1, return Decimal128ValueToObject(+∞𝔻).
    3. Otherwise, return Decimal128ValueToObject(-∞𝔻).
  9. If d2 is +∞𝔻, then
    1. If sign(d1) = -1, return Decimal128ValueToObject(−0𝔻).
    2. Otherwise, return Decimal128ValueToObject(+0𝔻).
  10. If d2 is -∞𝔻, then
    1. If sign(d1) = -1, return Decimal128ValueToObject(+0𝔻).
    2. Otherwise, return Decimal128ValueToObject(−0𝔻).
  11. If d2 is +0𝔻, then
    1. If d1 is +0𝔻 or -0𝔻, return Decimal128ValueToObject(NaN𝔻).
    2. If d1 < 0, return Decimal128ValueToObject(-∞𝔻).
    3. Otherwise, return Decimal128ValueToObject(+∞𝔻).
  12. If d2 is −0𝔻, then
    1. If d1 is +0𝔻 or -0𝔻, return Decimal128ValueToObject(NaN𝔻).
    2. If d1 < 0, return Decimal128ValueToObject(+∞𝔻).
    3. Otherwise, return Decimal128ValueToObject(-∞𝔻).
  13. If d1 is +0𝔻, then
    1. If d2 < 0, return Decimal128ValueToObject(−0𝔻).
    2. Otherwise, return Decimal128ValueToObject(+0𝔻).
  14. If d1 is −0𝔻, then
    1. If d2 < 0, return Decimal128ValueToObject(+0𝔻).
    2. Otherwise, return Decimal128ValueToObject(−0𝔻).
  15. Let quotient be d1 / d2.
  16. Return Decimal128ValueToObject(RoundToDecimal128Domain(quotient)).
Note

This operation follows the specification in Section 5.4.1 of IEEE 754-2019.

2.11 Decimal128.prototype.remainder ( x )

This method computes the remainder upon dividing the current Decimal128 object by another one. The computation proceeds as though infinite precision and unbounded range were available, rounding, if necessary.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 or d2 is NaN𝔻, return Decimal128ValueToObject(NaN𝔻).
  7. If d1 is +∞𝔻 or -∞𝔻, return Decimal128ValueToObject(NaN𝔻).
  8. If d2 is +∞𝔻 or -∞𝔻, return Decimal128ValueToObject(d1).
  9. If d2 is +0𝔻 or −0𝔻, return Decimal128ValueToObject(NaN𝔻).
  10. If d1 is +0𝔻 or −0𝔻, return Decimal128ValueToObject(d1).
  11. Assert: d2 ≠ 0.
  12. Let quotient be d1 / d2.
  13. Let q be truncate(quotient).
  14. Let r be d1 - (d2 × q).
  15. If r = 0, and d1 < 0, return Decimal128ValueToObject(−0𝔻).
  16. Otherwise, return Decimal128ValueToObject(r).
Note

The remainder operation specified here deviates from the IEEE 754-2019 remainder operation (defined there in Section 5.3.1). We follow the the remainder operation for Number rather than IEEE 754, which specifies that, for example, the remainder 46 and 10 is -4 rather than 6.

2.12 Decimal128.prototype.compare ( x )

This method returns one of the four Number values -1𝔽, +0𝔽, 1𝔽, and NaN𝔽. It compares the mathematical value of the current Decimal128 object with that of another Decimal128 object.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 is NaN𝔻, return NaN𝔽.
  7. If d2 is NaN𝔻, return NaN𝔽.
  8. If d1 is +∞𝔻, then
    1. If d2 is +∞𝔻, return +0𝔽.
    2. Return 1𝔽.
  9. If d1 is -∞𝔻, then
    1. If d2 is -∞𝔻, return +0𝔽.
    2. Return -1𝔽.
  10. If d2 is +∞𝔻, return -1𝔽.
  11. If d2 is -∞𝔻, return 1𝔽.
  12. If MV(d1) < MV(d2), return -1𝔽.
  13. If MV(d2) < MV(d1), return 1𝔽.
  14. Otherwise, return +0𝔽.
Note

This operation combines the compareQuietEqual, compareQuietLess operations in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

2.13 Decimal128.prototype.equals ( x )

This method returns either true or false according as the current Decimal128 object has the same mathematical value as the given Decimal128 object. The value false is returned if the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 is NaN𝔻, return false.
  7. If d2 is NaN𝔻, return false.
  8. If d1 is +∞𝔻, then
    1. If d2 is +∞𝔻, return true.
    2. Otherwise, return false.
  9. If d1 is -∞𝔻, then
    1. If d2 is -∞𝔻, return true.
    2. Otherwise, return false.
  10. If d2 is +∞𝔻 or -∞𝔻, return false.
  11. If MV(d1) = MV(d2), return true.
  12. Otherwise, return false.
Note

This operation corresponds to the compareQuietEqual operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

2.14 Decimal128.prototype.notEquals ( x )

This method returns either true or false according as the current Decimal128 object has a strictly smaller mathematical value as that of the given Decimal128 object. The value false is returned if either the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 is NaN𝔻, return false.
  7. If d2 is NaN𝔻, return false.
  8. If d1 is +∞𝔻, then
    1. If d2 is +∞𝔻, return false.
    2. Otherwise, return true.
  9. If d1 is -∞𝔻, then
    1. If d2 is -∞𝔻, return false.
    2. Otherwise, return true.
  10. If d2 is +∞𝔻 or -∞𝔻, return true.
  11. If MV(d1) ≠ MV(d2), return true.
  12. Otherwise, return false.
Note

This operation corresponds to the compareQuietNotEqual operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

2.15 Decimal128.prototype.lessThan ( x )

This method returns either true or false according as the current Decimal128 object has the same mathematical value as the given Decimal128 object. The value false is returned if the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 is NaN𝔻, return false.
  7. If d2 is NaN𝔻, return false.
  8. If d1 is +∞𝔻, return false.
  9. If d1 is -∞𝔻, then
    1. If d2 is -∞𝔻, return false.
    2. Otherwise, return true.
  10. If d2 is +∞𝔻, return true.
  11. If d2 is -∞𝔻, return false.
  12. If MV(d1) < MV(d2), return true.
  13. Otherwise, return false.
Note

This operation corresponds to the compareQuietEqual operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

2.16 Decimal128.prototype.lessThanOrEqual ( x )

This method returns either true, false, or undefined according as the current Decimal128 object has the same or smaller mathematical value as the given Decimal128 object. The value false is returned if the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 is NaN𝔻, return false.
  7. If d2 is NaN𝔻, return false.
  8. If d1 is +∞𝔻, then
    1. If d2 is +∞𝔻, return true.
    2. Otherwise, return false.
  9. If d1 is -∞𝔻, return true.
  10. If d2 is +∞𝔻, return true.
  11. If d2 is -∞𝔻, return false.
  12. If MV(d1) ≤ MV(d2), return true.
  13. Otherwise, return false.
Note

This operation corresponds to the compareQuietLessEqual operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

2.17 Decimal128.prototype.greaterThan ( x )

This method returns either true, false according as the current Decimal128 object has a greater mathematical value as the given Decimal128 object. The value false is returned if either the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 is NaN𝔻, return false.
  7. If d2 is NaN𝔻, return false.
  8. If d1 is +∞𝔻, then
    1. If d2 is +∞𝔻, return false.
    2. Otherwise, return true.
  9. If d1 is -∞𝔻, return false.
  10. If d2 is +∞𝔻, return false.
  11. If d2 is -∞𝔻, return true.
  12. If MV(d1) > MV(d2), return true.
  13. Otherwise, return false.
Note

This operation corresponds to the compareQuietGreater operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

2.18 Decimal128.prototype.greaterThanOrEqual ( x )

This method returns either true, false according as the current Decimal128 object has a greater or equal mathematical value as the given Decimal128 object. The value *false is returned if the current Decimal128 object or the argument is a NaN.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Perform ? RequireInternalSlot(x, [[Decimal128Data]]).
  4. Let d1 be O.[[Decimal128Data]].
  5. Let d2 be x.[[Decimal128Data]].
  6. If d1 is NaN𝔻, return false.
  7. If d2 is NaN𝔻, return false.
  8. If d1 is +∞𝔻, return true.
  9. If d1 is -∞𝔻, then
    1. If d2 is -∞𝔻, return true.
    2. Otherwise, return false.
  10. If d2 is +∞𝔻, return false.
  11. If d2 is -∞𝔻, return true.
  12. If MV(d1) ≥ MV(d2), return true.
  13. Otherwise, return false.
Note

This operation corresponds to the compareQuietGreaterEqual operation in Section 5.6.1 (and explained in Section 5.11) of IEEE 754-2019.

2.19 Decimal128.prototype.round ( numFractionalDigits [ , roundingMode ] )

This method rounds the current Decimal128 object according to the specified rounding mode, which, if omitted, is the default rounding mode, with rounding taking place only after numFractionalDigits non-integer digits, which must be a non-negative integer Number.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. If numFractionalDigits is not a Number, throw a TypeError exception.
  4. If numFractionalDigits is not an integer, throw a RangeError exception.
  5. If roundingMode is neither undefined nor a String, throw a TypeError exception.
  6. If roundingMode is undefined, set roundingMode to the default rounding mode.
  7. If roundingMode is not a rounding mode, throw a RangeError exception.
  8. Let d be O.[[Decimal128Data]].
  9. If d is one of « NaN𝔻, +∞𝔻, -∞𝔻 » return Decimal128ValueToObject(d).
  10. If d is +0𝔻 or −0𝔻, return Decimal128ValueToObject(d).
  11. Let sign be sign(d).
  12. Let scaledV be d × 10(numFractionalDigits).
  13. If sign = -1, then
    1. Set scaledV to −scaledV.
    2. If roundingMode is "floor", set roundingMode to "ceil".
    3. Else if roundingMode is "ceil", set roundingMode to "floor".
  14. Let roundedScaledV be ApplyRoundingModeToPositive(scaledV, roundingMode).
  15. If sign = -1, set roundedScaledV to −roundedScaledV.
  16. Let rescaledRoundedV be roundedScaledV × 10(−numFractionalDigits).
  17. Return Decimal128ValueToObject(RoundToDecimal128Domain(rescaledRoundedV, roundingMode)).
Note

This operation follows the specification of the rounding mode attributes discussed in Section 4.3 of IEEE 754-2019.

2.20 Decimal128.prototype.scale10 ( n )

This method multiplies the current Decimal128 object by 10 raised to the given power.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. If n is not a Number, throw a TypeError exception.
  4. If n is not one of « NaN𝔽, +∞𝔽, -∞𝔽 », then
    1. If (n) is not an integer, throw a RangeError exception.
  5. Let d be O.[[Decimal128Data]].
  6. If d is NaN𝔻, +∞𝔻, or -∞𝔻, return Decimal128ValueToObject(d).
  7. If d is either +0𝔻 or −0𝔻, return Decimal128ValueToObject(d).
  8. If n is NaN𝔽, return Decimal128ValueToObject(NaN𝔻).
  9. If n is +∞𝔽, then
    1. If d > 0, return Decimal128ValueToObject(+∞𝔻).
    2. Otherwise, return Decimal128ValueToObject(-∞𝔻).
  10. If n is -∞𝔽, then
    1. If d > 0, return Decimal128ValueToObject(+0𝔻).
    2. Otherwise, return Decimal128ValueToObject(−0𝔻).
  11. Let w be d × 10(n).
  12. Return Decimal128ValueToObject(RoundToDecimal128Domain(w)).
Note

This operation follows the specification of the scaleB operation discussed in Section 5.3.3 of IEEE 754-2019.

2.21 Decimal128.prototype.toString ( [ options ] )

This method generates a String representation of the current Decimal128 object, in decimal format. Its behaviour is similar to that of Number’s toString by rendering the decimal in decimal notation, but will use exponential notation if the the magnitude of the number is less than 10-6 or greater than 1034.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. If options is not undefined, then
    1. If options is not an Object, throw a TypeError exception.
  4. Let d be O.[[Decimal128Data]].
  5. If d is NaN𝔻, return "NaN".
  6. If d is +∞𝔻, return "Infinity".
  7. If d is -∞𝔻, return "-Infinity".
  8. If d is +0𝔻, return "0".
  9. If d is −0𝔻, return "-0".
  10. If abs(d) < 10-6 or abs(d) ≥ 1034, return return Decimal128ToExponentialString(O).
  11. Otherwise, return Decimal128ToDecimalString(O).
Note

This operation follows the specification of the conversion of IEEE 754-2019 Decimal128 values to strings (external character sequences) discussed in Section 5.12 of IEEE 754-2019.

2.22 Decimal128.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of this method is used:

This method produces a String value that represents this Decimal128 object formatted according to the conventions of the host environment’s current locale. This method is implementation-defined, and it is permissible, but not encouraged, for it to return the same thing as toString.

The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.

2.23 Decimal128.prototype.toExponential ( [ options ] )

This method generates a String representation of the current Decimal128 object, in exponential format (e.g., "123e-4").

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. If options is not undefined, then
    1. If options is not an Object, throw a TypeError exception.
  4. Return Decimal128ToExponentialString(O).
Note

This operation follows the specification of the conversion of IEEE 754-2019 Decimal128 values to strings (external character sequences) discussed in Section 5.12 of IEEE 754-2019.

2.24 Decimal128.prototype.toFixed ( [ options ] )

This method generates a String representation of the current Decimal128 object, in decimal format, with a specified number of digits after the decimal point.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Let numDigits be +0𝔽.
  4. Let roundingMode be undefined.
  5. If options is not undefined, then
    1. If options is not an Object, throw a TypeError exception.
    2. Set numDigits to ? Get(options, "digits").
    3. Set roundingMode to ? Get(options, "roundingMode").
  6. If numDigits is not a Number, throw a TypeError exception.
  7. If numDigits is NaN𝔽, +∞𝔽, or -∞𝔽, throw a RangeError exception.
  8. Set numDigits to (numDigits).
  9. If numDigits < 0, throw a RangeError exception.
  10. If numDigits is not an integer, throw a RangeError exception.
  11. If roundingMode is undefined, set roundingMode to "halfEven".
  12. Else if roundingMode is not a String, throw a TypeError exception.
  13. Else if roundingMode is not a Decimal128 rounding mode, throw a RangeError exception.
  14. Let d be O.[[Decimal128Data]].
  15. If d is NaN𝔻, return "NaN".
  16. If d is +∞𝔻, return "Infinity".
  17. If d is -∞𝔻, return "-Infinity".
  18. If sign(d) = 1, let signPrefix be "", else let signPrefix be "-".
  19. If d is +0𝔻 or -0𝔻, then
    1. If numDigits = 0, then
      1. Return the concatenation of signPrefix and "0".
    2. Otherwise:
      1. Let trailingZeroes be "0" repeated numDigits times.
      2. Return the concatenation of signPrefix, "0", ".", and trailingZeroes.
  20. Set d to abs(d).
  21. Let scaledV be d × 10numDigits.
  22. Let roundedScaledV be ApplyRoundingModeToPositive(scaledV, roundingMode).
  23. Let remainder be scaledV - roundedScaledV.
  24. Let remainderStr be Decimal128ToDecimalString(remainder).
  25. Let integerDigits be the unique decimal string representation of roundedScaledV without leading zeroes.
  26. Let nonIntegerDigits be the substring of remainderStr from 0 to numDigits + 1.
  27. Let s be the concatenation of signPrefix, integerDigits, ".", and nonIntegerDigits.
  28. Return CanonicalizeDecimalString(s).
Note

This operation follows the specification of the conversion of IEEE 754-2019 Decimal128 values to strings (external character sequences) discussed in Section 5.12 of IEEE 754-2019.

2.25 Decimal128.prototype.toJSON ( )

It performs the following steps when called:

  1. Throw a TypeError exception.
Note

The behaviour of this operation aligns with that of the conversion of BigInt values to JSON using JSON.stringify.

2.26 Decimal128.prototype.toPrecision ( [ options ] )

This method generates a String representation of the current Decimal128 object, in decimal format, with a specified number of significant digits. If the precision argument is omitted or is undefined, this method is equivalent to toString. This method may produce results in exponential notation or decimal notation.

It performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Let precision be 0.
  4. Let roundingMode be undefined.
  5. If options is not undefined, then
    1. If options is not an Object, throw a TypeError exception.
    2. Let optPrecision be ? Get(options, "precision").
    3. If optPrecision is neither undefined nor a Number, throw a TypeError exception.
    4. If optPrecision is undefined, return Decimal128ToDecimalString(O).
    5. If precision is NaN𝔽, +∞𝔽 or +∞𝔽, throw a RangeError exception.
    6. Set roundingMode to ? Get(options, "roundingMode").
    7. Set precision to (precision).
  6. If precision is not an integer, throw a RangeError exception.
  7. If precision < 1, throw a RangeError exception.
  8. Let d be O.[[Decimal128Data]].
  9. If d is NaN𝔻, return "NaN".
  10. If d is +∞𝔻, return "Infinity".
  11. If d is -∞𝔻, return "-Infinity".
  12. If sign(d) = 1, let signPrefix be "", else let signPrefix be "-".
  13. If d is +0𝔻 or -0𝔻, then
    1. If precision = 1, then
      1. Return the string concatenation of signPrefix and "0".
    2. Else,
      1. Let additionalZeroes be the string "0" repeated precision times.
      2. Return the string concatenation of "0", ".", and additionalZeroes.
  14. Let q be the largest integer such that d × 10q is an integer.
  15. Let n be d × 10q.
  16. Let coefficient be the unique decimal representation of n without leading zeroes.
  17. Let numDigits be the string length of coefficient.
  18. If numDigits < precision, then
    1. Let s be Decimal128ToDecimalString(d).
    2. If d is an integer, then
      1. Let additionalZeroes be the string "0" repeated precision - numDigits times.
      2. Return the string concatenationof coefficient, ".", and additionalZeroes.
    3. Otherwise:
      1. Let additionalZeroes be the string "0" repeated precision - numDigits times.
      2. Return the string concatenationof _signPrefix, s and additionalZeroes.
  19. Else if numDigits = precision, then
    1. Return coefficient.
  20. Otherwise:
    1. Let exp be q + precision.
    2. Let scaled be d × 10-exp.
    3. Let scaledAndRounded be ApplyRoundingModeToPositive(scaled, roundingMode).
    4. Assert: scaledAndRounded is not an integer.
    5. Let s be Decimal128ToDecimalString(scaledAndRounded).
    6. Let renderedQ be the unique decimal string representation of q.
    7. Return the string concatenation of signPrefix, s, "e", and renderedQ.
Note

This operation follows the specification of the conversion of IEEE 754-2019 Decimal128 values to strings (external character sequences) discussed in Section 5.12 of IEEE 754-2019.

2.27 Decimal128.prototype.valueOf ( x )

This method performs the following steps when called:

  1. Throw a TypeError exception.

3 Numbers and Dates

3.1 Number Objects

3.1.1 The Number Constructor

3.1.1.1 Number ( value )

This function performs the following steps when called:

  1. If value is present, then
    1. If value is an object that has an [[Decimal128Data]] internal slot, then
      1. Let d be value.[[Decimal128Data]].
      2. Let serialized be Decimal128ToExponentialString(d).
      3. Let n be ! ToNumber(serialized).
    2. Else,
      1. Let prim be ? ToNumeric(value).
      2. If prim is a BigInt, let n be 𝔽((prim)).
      3. Otherwise, let n be prim.
  2. Else,
    1. Let n be +0𝔽.
  3. If NewTarget is undefined, return n.
  4. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%Number.prototype%", « [[NumberData]] »).
  5. Set O.[[NumberData]] to n.
  6. Return O.

3.2 BigInt Objects

3.2.1 The BigInt Constructor

3.2.1.1 BigInt ( value )

This function performs the following steps when called:

  1. If NewTarget is not undefined, throw a TypeError exception.
  2. If value has a [[Decimal128Data]] internal slot, return ? Decimal128ToBigInt(value).
  3. Let prim be ? ToPrimitive(value, number).
  4. If prim is a Number, return ? NumberToBigInt(prim).
  5. Otherwise, return ? ToBigInt(prim).

3.2.1.1.1 Decimal128ToBigInt ( number )

The abstract operation Decimal128ToBigInt takes argument number (an Object with a [[Decimal128Data]] internal slot) and returns either a normal completion containing a BigInt or a throw completion. It performs the following steps when called:

  1. Let d be number.[[Decimal128Data]].
  2. If d is NaN𝔻, +∞𝔻 or -∞𝔻, throw a RangeError exception.
  3. If d is +0𝔻 or −0𝔻, return (0).
  4. If d is an integer, return ((d)).
  5. Otherwise, throw a RangeError exception.

4 Amendments to the ECMAScript® 2024 Internationalization API Specification

Editor's Note

This section lists amendments which must be made to ECMA-402, the ECMAScript® 2024 Internationalization API Specification. Text to be added is marked like this, and text to be deleted is marked like this. Blocks of unmodified text between modified sections are marked by [...].

4.1 Properties of the Decimal128 Prototype Object

4.1.1 Decimal128.prototype.toLocaleString ( [ locales [ , options ] ] )

This definition supersedes the definition provided in es2024, 2.22.

This function performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[Decimal128Data]]).
  3. Let numberFormat be ? Construct(%Intl.NumberFormat%, « locales, options »).
  4. Return FormatNumeric(numberFormat, O.[[Decimal128Data]]).

4.2 NumberFormat Objects

4.2.1 Abstract Operations for NumberFormat Objects

4.2.1.1 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 either a mathematical value, or one of 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. If value has a [[Decimal128Data]] internal slot, then
    1. Let d be value.[[Decimal128Data]].
    2. If d is NaN𝔻, return not-a-number.
    3. If d is +∞𝔻, return positive-infinity.
    4. If d is -∞𝔻, return negative-infinity.
    5. Return d.
  2. Let primValue be ? ToPrimitive(value, number).
  3. If Type(primValue) is BigInt, return (primValue).
  4. If Type(primValue) is String, then
    1. Let str be primValue.
  5. Else,
    1. Let x be ? ToNumber(primValue).
    2. If x is -0𝔽, return negative-zero.
    3. Let str be Number::toString(x, 10).
  6. Let text be StringToCodePoints(str).
  7. Let literal be ParseText(text, StringNumericLiteral).
  8. If literal is a List of errors, return not-a-number.
  9. Let intlMV be the StringIntlMV of literal.
  10. If intlMV is a mathematical value, then
    1. Let rounded be RoundMVResult(abs(intlMV)).
    2. If rounded is +∞𝔽 and intlMV < 0, return negative-infinity.
    3. If rounded is +∞𝔽, return positive-infinity.
    4. If rounded is +0𝔽 and intlMV < 0, return negative-zero.
    5. If rounded is +0𝔽, return 0.
  11. Return intlMV.

4.3 PluralRules Objects

4.3.1 Abstract Operations for PluralRules Objects

4.3.1.1 ResolvePlural ( pluralRules, n )

The abstract operation ResolvePlural takes arguments pluralRules (an Intl.PluralRules) and n (a Number or an Object with an [[Decimal128Data]] internal slot) and returns a Record with fields [[PluralCategory]] ("zero", "one", "two", "few", "many", or "other") and [[FormattedString]] (a String). The returned Record contains two string-valued fields describing n according to the effective locale and the options of pluralRules: [[PluralCategory]] characterizing its plural category, and [[FormattedString]] containing its formatted representation. It performs the following steps when called:

  1. If n is +∞𝔽 or -∞𝔽, then
    1. Let s be ! ToString(n).
    2. Return the Record { [[PluralCategory]]: "other", [[FormattedString]]: s }.
  2. If n is an Object with a [[Decimal128Data]] internal slot, then
    1. Let d be n.[[Decimal128Data]].
    2. If d is NaN𝔻, return the Record { [[PluralCategory]]: "other", [[FormattedString]]: "NaN" } .
    3. If d is +∞𝔻 or -∞𝔻, then
      1. If n is +∞𝔻, let s be "Infinity", otherwise let s be "-Infinity".
      2. Return the Record { [[PluralCategory]]: "other", [[FormattedString]]: s }.
    4. Let n be 𝔽(n).
    5. Let s be ! ToString(n).
  3. Let locale be pluralRules.[[Locale]].
  4. Let type be pluralRules.[[Type]].
  5. If n is a Number, then
    1. Let res be FormatNumericToString(pluralRules, (n)).
  6. Else,
    1. Let res be FormatNumericToString(pluralRules, n).
  7. Let s be res.[[FormattedString]].
  8. Let operands be GetOperands(s).
  9. Let p be PluralRuleSelect(locale, type, n, operands).
  10. Return the Record { [[PluralCategory]]: p, [[FormattedString]]: s }.

4.3.1.2 ResolvePluralRange ( pluralRules, x, y )

The abstract operation ResolvePluralRange takes arguments pluralRules (an Intl.PluralRules), x (a Number or an Object with a [[Decimal128Data]] internal slot), and y (a Number or an Object with a [[Decimal128Data]] internal slot) and returns either a normal completion containing either "zero", "one", "two", "few", "many", or "other", or a throw completion. The returned String value represents the plural form of the range starting from x and ending at y according to the effective locale and the options of pluralRules. It performs the following steps when called:

  1. If x is NaN or NaN𝔻 or y is NaNor NaN𝔻, throw a RangeError exception.
  2. Let xp be ResolvePlural(pluralRules, x).
  3. Let yp be ResolvePlural(pluralRules, y).
  4. If xp.[[FormattedString]] is yp.[[FormattedString]], then
    1. Return xp.[[PluralCategory]].
  5. Let locale be pluralRules.[[Locale]].
  6. Let type be pluralRules.[[Type]].
  7. Return PluralRuleSelectRange(locale, type, xp.[[PluralCategory]], yp.[[PluralCategory]]).

A Copyright & Software License

Copyright Notice

© 2024 Jesse Alama, Waldemar Horwat

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.