22

In Kotlin I have seen that for function a.mod(n), if a is negative the result is negative. Which is not what modulo is supposed to do. What can I do to have always positive modulo?

For example:

(-2).mod(9)

returns -2 and should be 7.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Damia Fuentes
  • 5,308
  • 6
  • 33
  • 65
  • 1
    Actually the negative sign is expected here, since that's how mod works in the majority of languages. https://stackoverflow.com/questions/11630321/why-does-c-output-negative-numbers-when-using-modulo – egor.zhdan Nov 23 '17 at 12:01
  • 10
    Just because it's common doesn't mean it's right. I've *never* wanted the C++ behavior, and always wanted the mathematical behavior. Consider the extremely common case of cycling through an array with `arrayOfStuff[curIndex - 1]`. When current index is zero, would you rather wrap around to the end, or throw an exception? – Tim has moved to Codidact Sep 08 '19 at 15:17
  • 1
    Who thought that having a negative result for mod was a good idea (in Kotlin)?? – dstibbe Jul 12 '22 at 09:37

4 Answers4

18

The best answer is Math.floorMod() as Paul Lammertsma mentioned in a comment, since it is the most mathematically correct: It always returns a value between zero (inclusive) and the divisor (exclusive), and does so regardless of whether either or both arguments are negative.

It's even invariant across flipping the signs of all the inputs and output:

Math.floorMod(11, 9) => 2
Math.floorMod(-11, -9) => -2

Math.floorMod(-11, 9) => 7
Math.floorMod(11, -9) => -7

Math.floorMod is available since JDK 1.8.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
12

In version kotlin 1.1 mod is deprecated because it was calculating the remainder of the division, which can be negative. Thats why they changed to rem, more similar name to its functionality. If you want a modulo function in Kotlin, and the majority of languages, you can use this:

r = (a).rem(n)
if (r < 0) r += n
Damia Fuentes
  • 5,308
  • 6
  • 33
  • 65
11

In Kotlin 1.5 the behavior changed and (-11).mod(9) == 7 as OP expected. In general,the result of mod will have the same sign as the divisor.

Note that operator % is still rem, so (-11) % 9 == -2.

Source: https://blog.jetbrains.com/kotlin/2021/04/kotlin-1-5-0-rc-released/

sbarzowski
  • 2,707
  • 1
  • 20
  • 25
0

For carousel array access there is a solution that works with % or rem as well as long as the negative is not below the size of the array. So if you rotate in an array with size 16

( 11 + 16 ) % 16) => 11

( -11 + 16 ) % 16) => 5

( -15 + 16 ) % 16) => 1

( -16 + 16 ) % 16) => 0

( 0 + 16 ) % 16 => 0

There is no need to call an extra function so this will be faster I expect (not tested).

( 16 + 16 ) % 16 => 0

Jan
  • 35
  • 4