I am trying to calculate (6.6 % 1.1). I expect this to be 0, but I get 1.0999999999999996. You can easily reproduce this in the javascript console. My guess its an interal rounding bug? How do you solve this issue?
-
8To answer the real question: You should not use the modulo operator on non-integer numbers. The problem is that `6.6 / 1.1` is not `6.0` but `5.999999999999999`, which will then be rounded down to `5` instead of `6`, so the difference is `6.6 - 5.0 * 1.1 = 1.1` instead of `6.6 - 6.0 * 1.1 = 0`. Do you really need the modulo operator? Usually, it is better to avoid it for non-natural numbers (or at least integers). – Tobias Jun 06 '16 at 16:22
-
Well, it's fine to use `%` on non-integers; it's got well-defined semantics. The problem is that most people would never guess what those semantics are without looking it up, and even then figuring out *why* they're like that is kind-of challenging. – Pointy Jun 06 '16 at 16:26
-
Consider using https://github.com/MikeMcl/bignumber.js/ – Gilad Artzi Jun 06 '16 at 16:33
3 Answers
The %
operator acts on non-integer values in a way that's not exactly obvious. In an expression
n % d
what JavaScript does is find the biggest integer (I'll call it q
to mirror the spec) that's less than n / d
. It then computes the product d * q
, and the result is the difference n - (d * q)
.
(I've ignored the sign issue for simplicity.)
The idea makes sense of you think about integer remainders: if n
and d
are integers, then the formulas above make perfect sense. Take 17 % 3
. Well 17 / 3
is 5.something
, so q
is 5
and the remainder is 17 - (5 * 3)
or 2
.
In your case, that process is made a little confusing by the fact that, with standard IEEE 754 floating point, 6.6 / 1.1
is not 6
; due to precision with representing decimal floating point values with binary floating point, it's just a tiny bit less than 6
. Thus, when q
is calculated, it comes out to 5
instead of 6
. The answer is thus 6 - (5 * 1.1)
, or 6 - 5.5
, which is (again, imprecision) just a tiny bit less than 1.1
.

- 405,095
- 59
- 585
- 614
JavaScript use IEEE double-precision to store floating point numbers, so 6.6 is 6.5999999 (I guess?). You can use
(66 % 11)/10
to avoid errors.

- 311
- 1
- 8
As the others have noted, you're seeing rounding effects from IEEE-754 floating point numbers. This isn't unique to JavaScript:
$ python
>>> 6.6 % 1.1
1.0999999999999992
The way to deal with float problems is to use an arbitrary precision math library:
For example, with big.js:
x = new Big(6.6)
// Big {s: 1, e: 0, c: Array[2]}
y = new Big(1.1)
// Big {s: 1, e: 0, c: Array[2]}
x.mod(y).toString()
// "0"

- 21
- 4