In Scala, why could remainder (%) operator return a negative number?

37,389

Solution 1

In scala, why could remainder (%) operator return a negative number?

There are different conventions for the sign of the result of a modulo operation; Wikipedia has a good article on it. Scala, like most but by no means all programming languages, has the result take the sign of the dividend (the -3 in your case).

What is the preferred way to get the positive remainder in Scala?

I doubt there's a generally-agreed preferred way; if it were me, either use Math.floorMod, which gives a result with the sign of the divisor (2 in your example) instead of the dividend (this doesn't just mean the same value as % with a different sign, see the linked JavaDoc for details). Or just an if afterward (if (result < 0) { result += M; } [where M is the divisor, 2 in your example]).

Solution 2

The correct way to get the positive modulus is to add the divisor to the negative modulus:

(-18 % 5) + 5

Taking the absolute value will give you the wrong solution in this case, though it will work if the divisor happens to be 2.

If you don't know the sign of the dividend, you can do something like this:

((dividend % divisor) + divisor) % divisor

Solution 3

Using math.abs(-x % y) does not usually yield the same behavior as returning a positive modulus:

scala> math.abs(-7 % 3)
res46: Int = 1

But that's not what python (a language that returns a positive modulus) says:

In [14]: -7 % 3
Out[14]: 2

If we look at increments of 3 from -7:

-7, -4, -1, 2, ..

scala stops at -1, and python stops at 2.

Solution 4

I would like to add something to the existing answers. My preferred way to get the positive remainder is to add a new method to the Int type as follows:

object Extensions
{
    implicit class ExtendedInt (val i: Int) extends AnyVal {
        def positiveMod (m: Int) = {val x = i % m; if (x < 0) x + m else x}
    }
}

In the file where you want to use the method, import the implicit class with:

import Extensions._

Now you can do:

(-3).positiveMod(2)

You could also put the implicit class in a package object so you don't need to import when calling the function from the same package.

Share:
37,389
Hanfei Sun
Author by

Hanfei Sun

Just another stackoverflow user cs.cmu.edu/~hanfeis

Updated on July 09, 2022

Comments

  • Hanfei Sun
    Hanfei Sun almost 2 years

    For example, (-3) % 2 will return -1 instead of 1.

    What is the preferred way to get the positive remainder in Scala? Such as (((-3) % 2) + 2) % 2, or abs(-3 % 2)?