The % operator is the reminder operator in Java. In other languages, it may be called modulo operator.

”%”, which divides one operand by another and returns the remainder as its result.

It seems a simple operator, by looking at example code like this, 10 % 7 = 3.

However, the % operator may return a negative value.

  assertEquals(-1, -9 % 2, "return negative value here");
  assertEquals(1, 9 % -2, "return positive value here");

It’s because Java’s reminder implementation uses “truncated division”. See details in this Wiki page. The “truncation (integer part)” of -9 / 2, i.e. -4.5, is -4. So,

  -9 % 2 = -9 - 2 * (-4) = -9 - (-8) = -1

For the 9 % -2 case, the “truncation” is also -4. However,

  9 % -2 = 9 - (-2) * (-4) = 9 - 8 = 1

A Problem

Sometime, this % returning negative behavior may cause problems.

  var batches = 10;
  // ... some RxJava code
  .groupBy(input -> Objects.hash(input) % batches)
  //...

For example, in above code you may want to split your work into 10 batches. However, because the Objects.hash() may return negative hash code, Objects.hash(input) % 10 has 19 possible values (integers), from -9 to 9. So unexpectedly, your work is split int 19 batches.

A Rescue

Java 8 provides a Math.floorMod() method, which can be used in situations like above. According to its Javadoc,

If the signs of the arguments are the same, the results of floorMod and the % operator are the same.

If the signs of the arguments are different, the results differ from the % operator.

floorMod(+4, -3) == -2;   and (+4 % -3) == +1
floorMod(-4, +3) == +2;   and (-4 % +3) == -1
floorMod(-4, -3) == -1;   and (-4 % -3) == -1

The floorMod(x, y) is calculated using below relationship.

floorDiv(x, y) * y + floorMod(x, y) == x

And for the Math.floorDiv() method, its Javadoc says

Returns the largest (closest to positive infinity) int value that is less than or equal to the algebraic quotient.

For example, floorDiv(-4, 3) == -2, whereas (-4 / 3) == -1.

Given dividend is -4 and divisor is 3, its algebraic quotient is -1.333333. “The largest (closest to positive infinity) int value that is less than or equal to” -1.333333 is -2, not -1 which is larger than the quotient. Therefore, floorDiv(-4, 3) == -2.

  floorMod(-4, 3) = -4 - floorDiv(-4, 3) * 3 = -4 - (-2)*3 = 2