Math.round(value, decimalPrecision) proposal

The proposal is about adding the support to the second parameter of the Math.round function defined in 21.3.2.28 Math.round ( x ) in the ES2023 release (https://ecma-international.org/wp-content/uploads/ECMA-262_14th_edition_june_2023.pdf).

The proposal adds the second parameter: Math.round( x, decimalPrecision ), where precision determines the number of decimal digits in the fraction of rounded value, e.g.:

  • Math.round(1.275, 1) -> 1.3
  • Math.round(1.275, 3) -> 1.275
  • Math.round(1.275, 5) -> 1.275
  • Math.round(1.275) -> 1 (same as it was without the second param)

On one hand I'm aware this is rather simple. But on the other hand, I see developers re-introducing the function over and over again. Sometimes even with bugs: there is Number.prototype.toFixed, which does a similar thing, however it returns an array which some people forget to convert. All in all, if Math.round was doing rounding the right way, I believe this small aspect would become simpler.

Will appreciate any feedback, thanks in advance!

1 Like

Adding a new parameter to Math.round looks unlikely to be web safe:

sourcegraph context:global lang:JavaScript ".map(Math.round)"

Code using .map(Math.round) are relying on it being a unary function.

@aclaymore makes sense, thank you. However, I couldn't run the query:

Unable To Process Query
Search context not found

not sure if I'm missing some access or the query is invalid (?)

Link edited. Seemed like it didn't url escape in a way discourse liked. Please try again.

Thank you very much @aclaymore. Will use https://sourcegraph.com further. So the only alternative in this situation is to provide a new method on Math. Does this sole fact (separate method instead of extending existing one) make it anyhow less likely to be taken into account by TC39?

I haven't got the impression that we are at a point of not adding new static methods onto the Math namespace. Though I imagine, as with all new things, it would need to justify its usefulness. Showing the extent of the issue in JS and how other languages have approached it are common initial steps.

Independent of web compat concerns, I have numerical stability concerns down the vein of https://0.30000000000000004.com/. For instance, if you implement Math.round(value, digits) as the obvious Math.round(value * (10**digits)) / (10**digits), you get the very erroneous result 0.9999999999990001 for Math.round(0.999999999999, 20).

In general, you should always avoid rounding by a base other than the one your float is represented as (usually either 2 or 10). To do otherwise is to pretty much guarantee errors. Stuff like Number.prototype.toPrecision is fine, as it can do things to systemically avoid numerical error entirely. But rounding a binary float to the nearest decimal digit is not only hard to do, but also a precision hazard.