From 2407c34cfdd09c227b37db3547ccfcc3329ab063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 22 Sep 2025 20:16:09 +0200 Subject: [PATCH 1/6] Use significant digits only on the way in and out --- spec.emu | 115 ++++++++++++++++++++++++++----------------------------- 1 file changed, 54 insertions(+), 61 deletions(-) diff --git a/spec.emu b/spec.emu index 4906980..39f44bb 100644 --- a/spec.emu +++ b/spec.emu @@ -262,32 +262,6 @@ location: https://github.com/tc39/proposal-amount/ - -

RoundToSignificantDigits ( - _v_: a mathematical value, - _n_: a non-negative integer, - optional _roundingMode_: a rounding mode - ): a mathematical value -

-
-
description
-
It computes the closest approximation to a given mathematical value that has at most the given number of significant digits, rounding (if necessary) according to the given rounding mode.
-
- - 1. If _roundingMode_ is *undefined*, set _roundingMode_ to *"halfEven"*. - 1. If _v_ = 0, return 0. - 1. If v < 0, then - 1. Let _reverseRoundingMode_ be ReverseRoundingMode(_roundingMode_). - 1. Let _d_ be RoundToSignificantDigits(–_v_, _n_, _reverseRoundingMode_). - 1. Return –_d_. - 1. Let _e_ be the unique integer such that 10_e_ ≤ _v_ < 10_e_+1. - 1. Let _pow_ be _e_ - _n_. - 1. Let _m_ be _v_ × 10–_pow_. - 1. Let _rounded_ be ApplyRoundingModeToPositive(_m_, _roundingMode_). - 1. Return _rounded_ × 10_n_ + _e_. - -
-

RenderAmountValueWithFractionDigits ( _v_: an Intl mathematical value, @@ -340,6 +314,46 @@ location: https://github.com/tc39/proposal-amount/ + +

FractionToSignificantDigits ( + _value_: an Intl mathematical value, + _fractionDigits_: an integer + ): a non-negative integer +

+
+ + 1. If _value_ is one of ~not-a-number~, ~positive-infinity~, or ~negative-infinity~, then + 1. Return 0. + 1. If _value_ is one of 0 or ~negative-zero~, then + 1. Let _integerDigits_ be 1. + 1. Else, + 1. Let _e_ be the smallest integer such that _e_ > the base 10 logarithm of abs(_value_). + 1. Let _integerDigits_ be 1 + _e_. + 1. Assert: _integerDigits_ + _fractionDigits_ > 0. + 1. Return _integerDigits_ + _fractionDigits_. + +
+ + +

SignificantToFractionDigits ( + _value_: an Intl mathematical value, + _significantDigits_: an integer + ): an integer +

+
+ + 1. If _value_ is one of ~not-a-number~, ~positive-infinity~, or ~negative-infinity~, then + 1. Return 0. + 1. If _value_ is one of 0 or ~negative-zero~, then + 1. Let _integerDigits_ be 1. + 1. Else, + 1. Let _e_ be the smallest integer such that _e_ > the base 10 logarithm of abs(_value_). + 1. Let _integerDigits_ be 1 + _e_. + 1. Assert: _significantDigits_ > 0. + 1. Return _significantDigits_ - _integerDigits_. + +
+

GetAmountOptions ( _opts_: an Object @@ -389,47 +403,27 @@ location: https://github.com/tc39/proposal-amount/ 1. Let _parsed_ be ParseText(_toParse_, |StringNumericLiteral|). 1. If _parsed_ is a List of errors, then 1. Let _amountValue_ be ~not-a-number~. - 1. Let _numDigits_ be 0. 1. Else, 1. Let _intlMV_ be the StringIntlMV of _parsed_. 1. Let _amountValue_ be _intlMV_[0]. - 1. Let _numDigits_ be _intlMV_[1]. 1. Let _validatedOpts_ be ? GetAmountOptions(_opts_). - 1. Let _fractionDigits_ be _validatedOpts_.[[FractionDigits]]. 1. Let _roundingMode_ be _validatedOpts_.[[RoundingMode]]. + 1. Let _fractionDigits_ be _validatedOpts_.[[FractionDigits]]. 1. Let _significantDigits_ be _validatedOpts_.[[SignificantDigits]]. 1. Let _unit_ be _validatedOpts_.[[Unit]]. - 1. Let _O_ be OrdinaryObjectCreate(%Amount.prototype%, « [[FractionDigits]], [[SignificantDigits]], [[Unit]], [[Value]] »). - 1. If _amountValue_ is a mathematical value, then - 1. Let _roundedValue_ be _amountValue_. - 1. If both _significantDigits_ and _fractionDigits_ are *undefined*, then - 1. Set _significantDigits_ to _numDigits_. + 1. Let _O_ be OrdinaryObjectCreate(%Amount.prototype%, « [[FractionDigits]], [[Unit]], [[Value]] »). + 1. If _fractionDigits_ is *undefined*, then + 1. If _significantDigits_ is not *undefined*, then + 1. Set _fractionDigits_ to SignificantToFractionDigits(_amountValue_, _significantDigits_). + 1. Else if _amountValue_ is a mathematical value or ~negative-zero~, then 1. Set _fractionDigits_ to the CountFractionDigits of _toParse_. - 1. Else if _significantDigits_ is *undefined*, then - 1. Set _roundedValue_ be RoundAmountValueToFractionDigits(_amountValue_, _fractionDigits_, _roundingMode_). - 1. Let _e_ be the smallest non-negative integer such that _roundedValue_ × 10-_e_ is an integer. - 1. Let _scaledRoundedValue_ be _roundedValue_ × 10-_e_. - 1. If _scaledRoundedValue_ = 0, then - 1. Set _significantDigits_ to 1. - 1. Else, - 1. Let _l_ be the log-10 of abs(_scaledRoundedValue_). - 1. Set _significantDigits_ to floor(_l_) + 1. - 1. Otherwise: - 1. Set _roundedValue_ be RoundToSignificantDigits(_amountValue_, _significantDigits_, _roundingMode_). - 1. Let _digitStr_ be the unique decimal string representation of _roundedValue_ without duplicate leading zeroes. - 1. Set _fractionDigits_ to the CountFractionDigits of _digitStr_. - 1. Set _O_.[[Value]] to _roundedValue_. - 1. Set _O_.[[SignificantDigits]] to _significantDigits_. - 1. Set _O_.[[FractionDigits]] to _fractionDigits_. - 1. Else if _amountValue_ is ~minus-zero~, then - 1. Set _O_.[[Value]] to ~minus-zero~. - 1. Set _O_.[[SignificantDigits]] to _numDigits_. - 1. Assert: _numDigits_ ≥ 1. - 1. Set _O_.[[FractionDigits]] to _numDigits_ - 1. - 1. Otherwise: + 1. Else, + 1. Set _fractionDigits_ to 0. + 1. Set _O_.[[FractionDigits]] to _fractionDigits_. + 1. If _amountValue_ is a mathematical value, then + 1. Set _O_.[[Value]] to RoundAmountValueToFractionDigits(_amountValue_, _fractionDigits_, _roundingMode_). + 1. Else, 1. Set _O_.[[Value]] to _amountValue_. - 1. Set _O_.[[SignificantDigits]] to _numDigits_.. - 1. Set _O_.[[FractionDigits]] to 0. 1. If _unit_ is not *undefined* and _amountValue_ is not ~not-a-number~, set _O_.[[Unit]] to _unit_. 1. Return _O_. @@ -486,15 +480,14 @@ location: https://github.com/tc39/proposal-amount/ 1. Let _fractionDigits_ be _processedOptions_.[[FractionDigits]]. 1. Let _significantDigits_ be _processedOptions_.[[SignificantDigits]]. 1. Let _value_ be _O_.[[Value]]. + 1. If _significantDigits_ is not *undefined*, set _fractionDigits_ to SignificantToFractionDigits(_value_, _significantDigits_). 1. If _fractionDigits_ is not *undefined*, set _value_ to RoundAmountValueToFractionDigits(_value_, _fractionDigits_). - 1. Else if _significantDigits_ is not *undefined*, set _value_ to RoundToSignificantDigits(_value_, _significantDigits_). - 1. Let _N_ be OrdinaryObjectCreate(*"%Amount.prototype%"*, « [[FractionDigits]], [[SignificantDigits]], [[Unit]], [[Value]] »). + 1. Let _N_ be OrdinaryObjectCreate(*"%Amount.prototype%"*, « [[FractionDigits]], [[Unit]], [[Value]] »). 1. If _unit_ is not *undefined* and _O_.[[Unit]] is not *undefined*, then 1. If SameValueNonNumber(_unit_, _O_.[[Unit]]) is *false*, throw a *TypeError* exception. 1. Set _N_.[[Value]] to _value_. 1. Set _N_.[[Unit]] to _unit_. 1. Set _N_.[[FractionDigits]] to ℝ(_fractionDigits_). - 1. Set _N_.[[SignificantDigits]] to ℝ(_significantDigits_). 1. Return _N_. From 8ff04f99c8ca15ea5c9fa5d757ca974702d5a42f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 23 Sep 2025 11:32:41 +0200 Subject: [PATCH 2/6] Fix off-by-on error --- spec.emu | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/spec.emu b/spec.emu index 39f44bb..e248c64 100644 --- a/spec.emu +++ b/spec.emu @@ -327,8 +327,7 @@ location: https://github.com/tc39/proposal-amount/ 1. If _value_ is one of 0 or ~negative-zero~, then 1. Let _integerDigits_ be 1. 1. Else, - 1. Let _e_ be the smallest integer such that _e_ > the base 10 logarithm of abs(_value_). - 1. Let _integerDigits_ be 1 + _e_. + 1. Let _integerDigits_ be the smallest integer such that 10_integerDigits_ > abs(_value_). 1. Assert: _integerDigits_ + _fractionDigits_ > 0. 1. Return _integerDigits_ + _fractionDigits_. @@ -347,8 +346,7 @@ location: https://github.com/tc39/proposal-amount/ 1. If _value_ is one of 0 or ~negative-zero~, then 1. Let _integerDigits_ be 1. 1. Else, - 1. Let _e_ be the smallest integer such that _e_ > the base 10 logarithm of abs(_value_). - 1. Let _integerDigits_ be 1 + _e_. + 1. Let _integerDigits_ be the smallest integer such that 10_integerDigits_ > abs(_value_). 1. Assert: _significantDigits_ > 0. 1. Return _significantDigits_ - _integerDigits_. From 843ff7aa1154137c8a1017c57149c3e2a183334c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 23 Sep 2025 12:12:27 +0200 Subject: [PATCH 3/6] Ensure 0 has at least 1 significant digit --- spec.emu | 1 + 1 file changed, 1 insertion(+) diff --git a/spec.emu b/spec.emu index e248c64..4d49f99 100644 --- a/spec.emu +++ b/spec.emu @@ -325,6 +325,7 @@ location: https://github.com/tc39/proposal-amount/ 1. If _value_ is one of ~not-a-number~, ~positive-infinity~, or ~negative-infinity~, then 1. Return 0. 1. If _value_ is one of 0 or ~negative-zero~, then + 1. If _fractionDigits_ < 0, return 1. 1. Let _integerDigits_ be 1. 1. Else, 1. Let _integerDigits_ be the smallest integer such that 10_integerDigits_ > abs(_value_). From b2fecbcc2ac5d3310d016d782a63f7703bbd22a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 23 Sep 2025 12:22:25 +0200 Subject: [PATCH 4/6] Update SignificantToFractionDigits type --- spec.emu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.emu b/spec.emu index 4d49f99..bb8acd1 100644 --- a/spec.emu +++ b/spec.emu @@ -337,7 +337,7 @@ location: https://github.com/tc39/proposal-amount/

SignificantToFractionDigits ( _value_: an Intl mathematical value, - _significantDigits_: an integer + _significantDigits_: a positive integer ): an integer

From 4d177e189d3ef1e9e1b99c989e5315331b6e543e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 23 Sep 2025 20:39:03 +0200 Subject: [PATCH 5/6] Fix signature of RoundAmountValueToFractionDigits --- spec.emu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.emu b/spec.emu index bb8acd1..a48a8ca 100644 --- a/spec.emu +++ b/spec.emu @@ -237,7 +237,7 @@ location: https://github.com/tc39/proposal-amount/

RoundAmountValueToFractionDigits( _v_: a mathematical value, - _n_: a non-negative integer, + _n_: an integer, optional _roundingMode_: a rounding mode ): a mathematical value

From b4445172fc9725831b81ba8caec25f6b4f59ab85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Wed, 24 Sep 2025 00:12:24 +0200 Subject: [PATCH 6/6] Allow negative fractionDigits in GetAmountOptions --- spec.emu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.emu b/spec.emu index a48a8ca..4e1a7ba 100644 --- a/spec.emu +++ b/spec.emu @@ -370,7 +370,7 @@ location: https://github.com/tc39/proposal-amount/ 1. Let _unit_ be ? GetOption(_opts_, *"unit"*, ~string~, ~empty~, *undefined*). 1. If _fractionDigits_ is not *undefined*, then 1. If _significantDigits_ is not *undefined*, throw a *RangeError* exception. - 1. If _fractionDigits_ is not a non-negative integral number, throw a *RangeError* exception. + 1. If _fractionDigits_ is not an integral number, throw a *RangeError* exception. 1. Else if _significantDigits_ is not *undefined*, then 1. If _significantDigits_ is not an integral number, throw a *RangeError* exception. 1. If ℝ(_significantDigits_) < 1, throw a *RangeError* exception.