Ecma262: Definition of modulo is broken

Created on 21 Apr 2020  ยท  10Comments  ยท  Source: tc39/ecma262

The change to explicitly note mathematical values broke the definition of modulo in the spec:

The notation โ€œ_x_ modulo _t_ _y_โ€ (_y_ must be finite and nonzero) computes a value _k_ of the same sign as _y_ (or zero) such that abs _t_(_k_) <_t_ abs _t_(_y_) and _x_ -_t_ _k_ = _q_ ร—_t_ _y_ for some integer _t_ _q_.

where _t_ is either โ„ for mathematical numbers or ๐”ฝ for IEEE doubles.

This definition of modulo works only when _t_ is โ„. The formula it uses is not meant to be used with numbers that are not mathematical numbers and breaks badly when _t_ is ๐”ฝ. There are multiple issues with finite precision and rounding, overflow, and underflow.

For example, this definition produces the nonsensical result that the exact IEEE double 200000000000000032๐”ฝ modulo๐”ฝ 100๐”ฝ is, among other things, 19๐”ฝ because 200000000000000032๐”ฝ -๐”ฝ 19๐”ฝ = 2000000000000000๐”ฝ ร—๐”ฝ 100๐”ฝ. The correct answer, of course, is 32๐”ฝ.

Similarly, by this definition, 4๐”ฝ modulo 2๐”ฝ evaluates to, among other things, 1.74e-75๐”ฝ because 4๐”ฝ -๐”ฝ 1.74e-75๐”ฝ = 2๐”ฝ ร—๐”ฝ 2๐”ฝ.

To fix it, use the formula only for the mathematical definition of modulo. If you need to define modulo on ๐”ฝ, do it by converting to and from mathematical numbers.

spec bug

All 10 comments

@waldemarhorwat Would you be willing to send a PR with your suggested fix?

cc @littledan @caiolima

@michaelficarra will do. It's a bit tricky because I don't want to define it for things like ยฑโˆž and NaN so I need to go through every point of use to see if those can arise. There are also some issues with the definition of _abs_ in this section.

Looking forward to seeing the PR for this.

For reference, some places in ES2019 where modulo is used on Number values:

Having seen so many other bugs introduced by #1135, I've now come to the conclusion that, rather than trying to hack modulo, exponentiation, addition, subtraction, counters, etc., the best way to fix them is to revert #1135 and instead explicitly mark the places where Number or Decimal arithmetic should be used. See #1964.

It seems like the fix for this issue is quite simple, to make modulo only in terms of โ„ and disallow parameterizing it. Are there any downsides to this fix?

@littledan: Yes, that's what I'd recommend doing for modulo (and exponentiation, etc.).

Modulo also seems inconsistent when dealing with negatives. Mathematical Operations specifies that the result has the sign of the divisor, while Number::remainder specifies that the result has the sign of the dividend.

So modulo behaves one way and Number::remainder behaves another. That's not really an inconsistency, not in the sense of the spec contradicting itself.

Was this page helpful?
0 / 5 - 0 ratings