Intl API percent formatting question (spec related)

Norbert Lindenberg ecmascript at
Mon Aug 20 19:18:55 PDT 2012

On Aug 20, 2012, at 17:17 , Nebojša Ćirić wrote:

> One of the tests was failing with a message: 1.1% formatted as 2%.
> Looking at the algorithm for
> InitializeNumberFormat (numberFormat, locales, options), steps 25 - 29 I think the test shouldn't fail.

The actual formatting isn't in these steps - they just set up the parameters for it.

> 25. If s is "currency" then let mnfdDefault be cDigits; else let mnfdDefault be 0. // 0
> 26. Let mnfd be the result of calling the GetNumberOption abstract operation with arguments options,
> "minimumFractionDigits", 0, 20, and mnfdDefault. // 0
> 27. Set the [[minimumFractionDigits]] internal property of numberFormat to mnfd. // Still 0.
> 28. If s is "currency" then let mxfdDefault be max(mnfd, cDigits); else if s is "percent" then let mxfdDefault be
> max(mnfd, 0); else let mxfdDefault be max(mnfd, 3). // 0 in case of percent.
> 29. Let mxfd be the result of calling the GetNumberOption abstract operation with arguments options,
> "maximumFractionDigits", mnfd, 20, and mxfdDefault. // And 0 for percent again.
> So both [[minimumFractionDigits]] and [[maximumFractionDigits]] are 0 in case of "percent" formatting (except if user overrides it with corresponding options parameter).

So far correct.

> 1.1 should be (can't find it in the spec right now) rounded up, so it ends up as 2.

I don't think the spec says that. Look at the FormatNumber abstract operation:

- Step 3.b multiplies the value with 100 for percent formatting, so 0.011 becomes 1.1.

- ToRawFixed is called to convert this to a string.

- Step 1 of ToRawFixed sets f to 0 (based on [[maximumFractionDigits]]).

- Step 2 then is "Let n be an integer for which the exact mathematical value of n ÷ 10^f – x is as close to zero as possible. If there are two such n, pick the larger n." For n = 1, the value of the expression is -0.1, for n = 2, 0.9. -0.1 is closer to zero than 0.9, so we pick n = 1. For x = 1.5, n = 1 and n = 2 would be equally close, and then we'd pick the larger one, but for 1.1 the second sentence doesn't come into play.

- Step 3 turns this into the string "1", and since f is 0, and minFraction is maxFraction, and the string doesn't contain a period, and int is minInteger, nothing else happens to the string before it's returned.

> In order to pass the test I internally (ICU code) incremented number of fractional digits from 2 to 3 - 0.011 then formats as 1.1%. We should probably change defaults depending on what people expect with percent formatting.

"2%" would certainly be an unexpected result for 0.011, but "1%" seems quite reasonable. What people expect will vary depending on the data and the precision of their measurements. In some cases, you want one or two fractional digits, in others it may make more sense to ask for two significant digits. I unfortunately don't know what's most common.


> Did I miss something?
> -- 
> Nebojša Ćirić

More information about the es-discuss mailing list