在 Scala 中,为什么余数 (%) 运算符 return 可以是负数?

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

例如,(-3) % 2 将 return -1 而不是 1

在 Scala 中获得正余数的首选方法是什么?比如(((-3) % 2) + 2) % 2,或者abs(-3 % 2)?

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

模运算结果的符号有不同的约定; Wikipedia has a good article on it。 Scala 与大多数但绝不是所有编程语言一样,其结果采用红利符号(在您的情况下为 -3)。

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

我怀疑是否存在公认的首选方式;如果是我,要么使用 Math.floorMod,它给出的结果带有除数符号(在您的示例中为 2)而不是股息(这不仅仅意味着与 [= 相同的值13=] 带有不同的符号,有关详细信息,请参阅链接的 JavaDoc)。或者只是一个 if 之后(if (result < 0) { result += M; } [其中 M 是除数,2 在你的例子中])。

使用 math.abs(-x % y) 通常不会产生与返回正模数相同的行为:

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

但这不是 python(一种 returns 正模数的语言)所说的:

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

如果我们看从-7开始递增3:

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

scala停在-1python停在2

获得正模数的正确方法是将除数加到负模数上:

(-18 % 5) + 5

在这种情况下取​​绝对值会给你错误的解决方案,但如果除数恰好是 2,它会起作用。

如果你不知道红利的符号,你可以这样做:

((dividend % divisor) + divisor) % divisor

例如,如果你想从一个数组中过滤掉所有奇数元素,忽略负数或正数,你可以这样做:

arr.filter{x => Math.abs(x%2)==1}

我想对现有答案进行补充。我首选的获取正余数的方法是向 Int 类型添加一个新方法,如下所示:

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}
    }
}

在您要使用该方法的文件中,导入隐式 class :

import Extensions._

现在您可以:

(-3).positiveMod(2)

您还可以将隐式 class 放在一个包对象中,这样当您从同一个包调用函数时就不需要导入。