Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use `Intl.NumberFormat` with `maximumFractionDigits` and `maximumSignificantDigits` at once

When running

console.log(new Intl.NumberFormat('en-US', {
  minimumFractionDigits: 0,
  maximumFractionDigits: 0,
  maximumSignificantDigits: 3,
  minimumSignificantDigits: 1 
}).format(10.123456789));

I would expect the output to be 10. Instead for some reason it outputs 10.1 which breaks the maximumFractionDigits: 0 constraint. What's going on? Considering this constraint is ignored across browsers it seems this is according to specification, but I just can't phantom a reason for this.

like image 589
David Mulder Avatar asked Apr 24 '19 16:04

David Mulder


People also ask

What is Intl NumberFormat?

Intl.NumberFormat.prototype.format() Getter function that formats a number according to the locale and formatting options of this Intl.NumberFormat object. Intl.NumberFormat.prototype.formatToParts() Returns an Array of objects representing the number string in parts that can be used for custom locale-aware formatting.

What is maximumSignificantDigits?

maximumSignificantDigits. The maximum number of significant digits to use. Possible values are from 1 to 21; the default is 21.

What is maximumFractionDigits?

maximumFractionDigits is the maximum number of fraction digits to use, with possible values ranging from 0 to 20.


1 Answers

From the Intl.NumberFormat parameter descriptions (emphasis added):

The following properties fall into two groups: minimumIntegerDigits, minimumFractionDigits, and maximumFractionDigits in one group, minimumSignificantDigits and maximumSignificantDigits in the other. If at least one property from the second group is defined, then the first group is ignored.

There has to be some override behavior to handle property setting conflicts but in your example, one might reasonably wish that the override behavior was not quite so all or nothing (since making the adjustment for the fraction digits limitation falls within the specified range of significant digits). Unfortunately, the spec is simply to ignore any of the fraction or integer digit limitations if the significant digit properties are set.

If anyone comes looking for a way to utilize both types of properties to format a single number, below is a very basic example using the two constructors in succession (beware, this can get messy very quickly with more complex formatting requirements).

const sigDigits = (n, min, max, minf, maxf) => {
  let num = new Intl.NumberFormat('en-US', {
    minimumSignificantDigits: min,
    maximumSignificantDigits: max
  })
  .format(n);
  
  num = new Intl.NumberFormat('en-US', {
    minimumFractionDigits: minf,
    maximumFractionDigits: maxf
  })
  .format(num);
  
  return num;
};

const result = sigDigits(10.123456789, 1, 3, 0, 0);
console.log(result);
// 10
like image 112
benvc Avatar answered Sep 25 '22 02:09

benvc