Ecma-402 Proposal for Intl.NumberFormat round option

830 views
Skip to first unread message

Rafael Xavier

unread,
Feb 18, 2015, 7:53:22 AM2/18/15
to javascript-g...@googlegroups.com
Hello,

I've just added a proposal for Ecma-402 to add a new option for Intl.NumberFormat to allow selecting a rounding function different than round "half-even", e.g.,
new Intl.NumberFormat("en", {round: "floor"});
If you have any thoughts, they are welcome:
https://github.com/tc39/ecma402/pull/2

caridy

unread,
Feb 18, 2015, 3:01:16 PM2/18/15
to Rafael Xavier, javascript-g...@googlegroups.com
Rafael, thanks for putting the proposal together, and keep them coming :). Few notes:

1. how will the output vary for other locales? it seems that this is only applicable for smallest currency denotation in some locales. I’m worry about introducing a formatting option that might affect the way currency is visualized while the internals of the program will be using a different numeric value. E.g.: what if we format the total amount to be charged in a paypal form, and it says $10, while in reality we will charge 10.4 once we redirect to paypal. It seems to me that any operation with number belongs to the numbers realm in the business logic of the program. e.g.: 

let formatUsingFloorRounding = new Intl.NumberFormat("en").format(Math.floor(Math.PI));
// "3.141"

let formatCurrencyUsingCeilRounding = new Intl.NumberFormat("en", {
  style: "currency",
  currency: "USD",
  currencyDisplay: "symbol"
}).format(Math.ceil(9.991)); // or Math.trunc() or Math.round(), etc...
// "$10.00"

2. what will be the symmetry of this with the reflective Math api? I’m concern that the behavior of this formatting process might diverge from the Reflective `Math` 262 specification (I don’t know the details of the implementation though).

3. do other languages support this formatting rules for numbers? java? php? this is something we should analyze and document as part of the proposal.

Other logistics: I don’t think we should allocate this in stage 0 just yet, let’s just call it a proposal, and if the commite decides that we can process with it, then we set it to stage 0.

/caridy

--
You received this message because you are subscribed to the Google Groups "JavaScript Globalization" group.
To unsubscribe from this group and stop receiving emails from it, send an email to javascript-globali...@googlegroups.com.
To post to this group, send email to javascript-g...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/javascript-globalization/CADdLYspzsTrthWEqXcHzBL%2BibBKHU-h1YFsSvUfCs1HRnX_58A%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Rafael Xavier

unread,
Feb 18, 2015, 5:03:16 PM2/18/15
to caridy, Rick Waldron, Steven R. Loomis, javascript-g...@googlegroups.com
Hi Caridy,

Thanks for your questions.


1. how will the output vary for other locales? it seems that this is only applicable for smallest currency denotation in some locales. I’m worry about introducing a formatting option that might affect the way currency is visualized while the internals of the program will be using a different numeric value. E.g.: what if we format the total amount to be charged in a paypal form, and it says $10, while in reality we will charge 10.4 once we redirect to paypal. It seems to me that any operation with number belongs to the numbers realm in the business logic of the program. e.g.:

Please, could you clarify? I'm confused, because: numbers/currencies are always rounded whether or not you specify the rounding method. It always uses the half-even round. Are you suggesting this behavior will always cause problems for applications and instead applications should always round the numbers themselves before using the formatter?

Math.round(), Math.floor(), Math.ceil(), etc do not round to a given decimal digit, only to integers, I'm assuming this has been used this way here as a simplified demonstration. Considering the application knows in advance which decimal place the round is going to take place and rounds the number as you suggest, should we enforce that usage? It's a lot of duplicate work: (b.i) if no options have been used, maximumFractionDigits defaults to 3, so in theory the application could round-in-advance numbers to the 3rd decimal place using a special rounding function that takes the decimal digit in for rounding, (b.ii) if minimumSignificantDigits and maximumSignificantDigits have been used, the formatter will round the number at a different decimal case depending of each value, so in theory the application could round-in-advance numbers using a special rounding function that takes the value and significant min and max values in for rounding. It seems to me a lot of work if the application simply wants to display the number rounded using its preferred method.

It's not always possible to know the decimal place in advance, currencies as an example (as you've mentioned). Note, it's not locale dependent. But, currency dependent.
let currencyFormattingOption = {style:"currency", currency: "USD", currencyDisplay: "symbol"};
new Intl.NumberFormat("en", currencyFormattingOption).format(9); // "$9.00"
new Intl.NumberFormat("en", currencyFormattingOption).format(9); // "¥9"
Your paypal example is a perfect demonstration where formatting should use ceil instead of the default rounding. If it had shown $11 and charged $10.4, customer would be happy. :D Or more realistically, displaying $10.01, when value is $10.004 and have the backend to charge for the same displayed $10.01 would be fine. I want to emphasize that not necessarily the paypal example will have problems because of whether or not the number has been rounding in advance of the formatter on the client side. But, it will have a problem if the application is not well architected. Let me clarify, in this case the problem happens if it performs two different actions on the client vs. on the server.

2. what will be the symmetry of this with the reflective Math api? I’m concern that the behavior of this formatting process might diverge from the Reflective `Math` 262 specification (I don’t know the details of the implementation though).

I have no idea either. Perhaps Rick could weigh in.

3. do other languages support this formatting rules for numbers? java? php? this is something we should analyze and document as part of the proposal.

I know Unicode Technical Standard #35 (UTS#35) clearly suggests a rounding option: "An implementation may allow the specification of a rounding mode to determine how values are rounded" here.

Steven, does ICU allow that?

I will reply if I find out how this work for other programming languages.

Other logistics: I don’t think we should allocate this in stage 0 just yet, let’s just call it a proposal, and if the commite decides that we can process with it, then we set it to stage 0.

Sure, I'm ok with whatever name. On https://github.com/tc39/ecma402 table, there's a stage column. I'm using 0 there, because it will only be inserted if the PR is accepted and merged.


Please, just let me know on any other question and thank you so far.

Rafael Xavier

unread,
Feb 18, 2015, 5:05:53 PM2/18/15
to caridy, Rick Waldron, Steven R. Loomis, javascript-g...@googlegroups.com
EDIT:
new Intl.NumberFormat("en", {style:"currency", currency: "JPY", currencyDisplay: "symbol"}).format(9); // "¥9"

Rick Waldron

unread,
Feb 18, 2015, 5:09:36 PM2/18/15
to Rafael Xavier, caridy, Steven R. Loomis, javascript-g...@googlegroups.com
On Wed Feb 18 2015 at 5:03:15 PM Rafael Xavier <rxav...@gmail.com> wrote:
Hi Caridy,

Thanks for your questions.


1. how will the output vary for other locales? it seems that this is only applicable for smallest currency denotation in some locales. I’m worry about introducing a formatting option that might affect the way currency is visualized while the internals of the program will be using a different numeric value. E.g.: what if we format the total amount to be charged in a paypal form, and it says $10, while in reality we will charge 10.4 once we redirect to paypal. It seems to me that any operation with number belongs to the numbers realm in the business logic of the program. e.g.:

Please, could you clarify? I'm confused, because: numbers/currencies are always rounded whether or not you specify the rounding method. It always uses the half-even round. Are you suggesting this behavior will always cause problems for applications and instead applications should always round the numbers themselves before using the formatter?

Math.round(), Math.floor(), Math.ceil(), etc do not round to a given decimal digit, only to integers, I'm assuming this has been used this way here as a simplified demonstration. Considering the application knows in advance which decimal place the round is going to take place and rounds the number as you suggest, should we enforce that usage? It's a lot of duplicate work: (b.i) if no options have been used, maximumFractionDigits defaults to 3, so in theory the application could round-in-advance numbers to the 3rd decimal place using a special rounding function that takes the decimal digit in for rounding, (b.ii) if minimumSignificantDigits and maximumSignificantDigits have been used, the formatter will round the number at a different decimal case depending of each value, so in theory the application could round-in-advance numbers using a special rounding function that takes the value and significant min and max values in for rounding. It seems to me a lot of work if the application simply wants to display the number rounded using its preferred method.

It's not always possible to know the decimal place in advance, currencies as an example (as you've mentioned). Note, it's not locale dependent. But, currency dependent.
let currencyFormattingOption = {style:"currency", currency: "USD", currencyDisplay: "symbol"};
new Intl.NumberFormat("en", currencyFormattingOption).format(9); // "$9.00"
new Intl.NumberFormat("en", currencyFormattingOption).format(9); // "¥9"
Your paypal example is a perfect demonstration where formatting should use ceil instead of the default rounding. If it had shown $11 and charged $10.4, customer would be happy. :D Or more realistically, displaying $10.01, when value is $10.004 and have the backend to charge for the same displayed $10.01 would be fine. I want to emphasize that not necessarily the paypal example will have problems because of whether or not the number has been rounding in advance of the formatter on the client side. But, it will have a problem if the application is not well architected. Let me clarify, in this case the problem happens if it performs two different actions on the client vs. on the server.

2. what will be the symmetry of this with the reflective Math api? I’m concern that the behavior of this formatting process might diverge from the Reflective `Math` 262 specification (I don’t know the details of the implementation though).

I have no idea either. Perhaps Rick could weigh in.

If the feature is specified as "use Math.foo", then there will be no divergence. If the feature requires its own additional semantics, then there will have to internal abstract operation definitions. 

TBH, I would recommend/prefer to stick with "Math.foo", but I may be over-simplifying this to myself.

Rick

Rick Waldron

unread,
Feb 18, 2015, 5:11:16 PM2/18/15
to Rafael Xavier, caridy, Steven R. Loomis, javascript-g...@googlegroups.com
On Wed Feb 18 2015 at 5:05:52 PM Rafael Xavier <rxav...@gmail.com> wrote:
EDIT:
new Intl.NumberFormat("en", {style:"currency", currency: "JPY", currencyDisplay: "symbol"}).format(9); // "¥9"


Sidenote: I wonder if this should actually be designed as a new class  ie. Intl.CurrencyFormat([locales [, options]])

Rick

Rick Waldron

unread,
Feb 18, 2015, 5:52:27 PM2/18/15
to Rafael Xavier, caridy, Steven R. Loomis, javascript-g...@googlegroups.com
That was a half-thought: I meant as a subclass with "pre-filled" style option. Now that I'm writing this follow up, I dislike the idea and am striking it.

Rick

Rafael Xavier

unread,
Feb 18, 2015, 6:55:22 PM2/18/15
to caridy, Rick Waldron, Steven R. Loomis, javascript-g...@googlegroups.com
On Wed, Feb 18, 2015 at 8:03 PM, Rafael Xavier <rxav...@gmail.com> wrote:
Hi Caridy,

Thanks for your questions.

1. how will the output vary for other locales? it seems that this is only applicable for smallest currency denotation in some locales. I’m worry about introducing a formatting option that might affect the way currency is visualized while the internals of the program will be using a different numeric value. E.g.: what if we format the total amount to be charged in a paypal form, and it says $10, while in reality we will charge 10.4 once we redirect to paypal. It seems to me that any operation with number belongs to the numbers realm in the business logic of the program. e.g.:

Please, could you clarify? I'm confused, because: numbers/currencies are always rounded whether or not you specify the rounding method. It always uses the half-even round. Are you suggesting this behavior will always cause problems for applications and instead applications should always round the numbers themselves before using the formatter?

Math.round(), Math.floor(), Math.ceil(), etc do not round to a given decimal digit, only to integers, I'm assuming this has been used this way here as a simplified demonstration. Considering the application knows in advance which decimal place the round is going to take place and rounds the number as you suggest, should we enforce that usage? It's a lot of duplicate work: (b.i) if no options have been used, maximumFractionDigits defaults to 3, so in theory the application could round-in-advance numbers to the 3rd decimal place using a special rounding function that takes the decimal digit in for rounding, (b.ii) if minimumSignificantDigits and maximumSignificantDigits have been used, the formatter will round the number at a different decimal case depending of each value, so in theory the application could round-in-advance numbers using a special rounding function that takes the value and significant min and max values in for rounding. It seems to me a lot of work if the application simply wants to display the number rounded using its preferred method.

It's not always possible to know the decimal place in advance, currencies as an example (as you've mentioned). Note, it's not locale dependent. But, currency dependent.
let currencyFormattingOption = {style:"currency", currency: "USD", currencyDisplay: "symbol"};
new Intl.NumberFormat("en", currencyFormattingOption).format(9); // "$9.00"
new Intl.NumberFormat("en", currencyFormattingOption).format(9); // "¥9"
Your paypal example is a perfect demonstration where formatting should use ceil instead of the default rounding. If it had shown $11 and charged $10.4, customer would be happy. :D Or more realistically, displaying $10.01, when value is $10.004 and have the backend to charge for the same displayed $10.01 would be fine. I want to emphasize that not necessarily the paypal example will have problems because of whether or not the number has been rounding in advance of the formatter on the client side. But, it will have a problem if the application is not well architected. Let me clarify, in this case the problem happens if it performs two different actions on the client vs. on the server.

2. what will be the symmetry of this with the reflective Math api? I’m concern that the behavior of this formatting process might diverge from the Reflective `Math` 262 specification (I don’t know the details of the implementation though).

I have no idea either. Perhaps Rick could weigh in.

3. do other languages support this formatting rules for numbers? java? php? this is something we should analyze and document as part of the proposal.

I know Unicode Technical Standard #35 (UTS#35) clearly suggests a rounding option: "An implementation may allow the specification of a rounding mode to determine how values are rounded" here.

Steven, does ICU allow that?

I will reply if I find out how this work for other programming languages.

Other logistics: I don’t think we should allocate this in stage 0 just yet, let’s just call it a proposal, and if the commite decides that we can process with it, then we set it to stage 0.

Sure, I'm ok with whatever name. On https://github.com/tc39/ecma402 table, there's a stage column. I'm using 0 there, because it will only be inserted if the PR is accepted and merged.

Rafael Xavier

unread,
Feb 18, 2015, 6:57:07 PM2/18/15
to Rick Waldron, caridy, Steven R. Loomis, javascript-g...@googlegroups.com
Caridy and Rick,

I understood that the option should accept a function (e.g., Math.ceil) instead of a string ("ceil").
https://github.com/rxaviers/ecma402-number-format-round-option/commit/68d2ad9847811c6229a92c82844654af7d4bfa68

Please, just let me know if I misunderstood you.
 

Rick

--
You received this message because you are subscribed to the Google Groups "JavaScript Globalization" group.
To unsubscribe from this group and stop receiving emails from it, send an email to javascript-globali...@googlegroups.com.
To post to this group, send email to javascript-g...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Edwin Hoogerbeets

unread,
Feb 18, 2015, 7:27:04 PM2/18/15
to javascript-g...@googlegroups.com
Rounding of currency specifically can get even more complicated than half-up, half-down, or round-to-the-nearest-even-number. Take a look at Tex Texin's page on currency formatting and rounding: http://www.xencraft.com/resources/multi-currency.html

Also note that in some countries such as Australia, they have done away with the smaller coins like pennies, so currencies are often rounded to the smallest coin when dealing with cash rather than electronic amounts. This is called "Swedish rounding" as it used to be used in Sweden. In the Australian example, the smallest coin is 5 cents, so the rounding is a little more complicated than rounding to a particular decimal point. Take a look at http://en.wikipedia.org/wiki/Swedish_rounding

As a user of the Intl object, I would prefer that I don't need to be an expert on which rounding methods are used with which locales. I would just like to make sure it is rounded properly for electronic or cash transactions types. Providing the name of a standard rounding function, or providing an optional rounding callback function is fine for making the API more general, but I would prefer that Intl.NumberFormat just "do the right thing" for the locale automatically when formatting currencies.

Edwin

caridy

unread,
Feb 18, 2015, 7:55:01 PM2/18/15
to Edwin Hoogerbeets, javascript-g...@googlegroups.com
Right, I completely agree with Edwin. And it was my understanding that the current implementation takes care of that in some degree (maybe we should just strike to make it better). This is what I see today:

new Intl.NumberFormat('en', {style: 'currency', currency: 'usd'}).format(100.223455879)   // "$100.223” in chrome and "$100.22” in firefox
new Intl.NumberFormat('fr',   {style: 'currency', currency: 'eur'}).format(100.125500009)   // "100,126 €” in chrome and “100,13 €” in firefox

As for the ceiling/flooring/truncating, I think those are match operations that has nothing to do with the locale data, those are simply universal operations on numbers, and they probably belong to the Math imperative api.

/caridy

--
You received this message because you are subscribed to the Google Groups "JavaScript Globalization" group.
To unsubscribe from this group and stop receiving emails from it, send an email to javascript-globali...@googlegroups.com.
To post to this group, send email to javascript-g...@googlegroups.com.

Rafael Xavier

unread,
Feb 19, 2015, 6:18:34 AM2/19/15
to caridy, Edwin Hoogerbeets, javascript-g...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages