Java 在Scala中,为什么余数(%)运算符可以返回负数?

Java 在Scala中,为什么余数(%)运算符可以返回负数?,java,scala,modulo,Java,Scala,Modulo,例如,(-3)%2将返回-1,而不是1 在Scala中获得正余数的首选方法是什么?例如((-3)%2)+2)%2,或abs(-3%2) 在scala中,为什么余数(%)运算符可以返回负数 模运算结果的符号有不同的约定。Scala与大多数编程语言一样,但绝不是所有编程语言,其结果都带有红利的符号(在您的例子中是-3) 在Scala中获得正余数的首选方法是什么 我怀疑是否有一个普遍同意的首选方式;如果是我,也可以使用,它给出的结果带有除数的符号(2,在您的示例中)而不是被除数(这不仅仅意味着与%相同

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

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

在scala中,为什么余数(%)运算符可以返回负数

模运算结果的符号有不同的约定。Scala与大多数编程语言一样,但绝不是所有编程语言,其结果都带有红利的符号(在您的例子中是
-3

在Scala中获得正余数的首选方法是什么

我怀疑是否有一个普遍同意的首选方式;如果是我,也可以使用,它给出的结果带有除数的符号(
2
,在您的示例中)而不是被除数(这不仅仅意味着与
%
相同的值带有不同的符号,有关详细信息,请参阅链接的JavaDoc)。或者只是一个
if
if(result<0){result+=M;}
[其中
M
是除数,在您的示例中
2
)。

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

scala> math.abs(-7 % 3)
res46: Int = 1
(-18 % 5) + 5
但python(一种返回正模的语言)并不是这么说的:

如果我们从-7看3的增量:

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

scala
-1
处停止,而
python
2
处停止

获得正模的正确方法是将除数与负模相加:

scala> math.abs(-7 % 3)
res46: Int = 1
(-18 % 5) + 5
在这种情况下,取绝对值会给出错误的解决方案,尽管如果除数正好是2,它会起作用

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

((dividend % divisor) + divisor) % divisor

例如,如果要从数组中过滤掉所有奇数元素,忽略负数或正数,可以执行以下操作:

((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}
    }
}
现在您可以执行以下操作:

(-3).positiveMod(2)

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

@RexKerr:欢迎编辑。:-)我得承认我不是一个数学高手。我已经将其复制到上面,但也许您可以进一步编辑,以解释OP的具体示例中的“模数基数”是什么;我看到的描述是关于除数和除数,而不是基数,我想你不是指基数。。。我想你指的是除数,看看文档中的
floorMod
,这就是我所做的编辑。遗憾的是
floorMod
只定义了
int
long
,而不是
float
double
;如果(r<0)r+除数,那么r'比另取一个%@yonil:Eh更有效。。。我对此表示怀疑。虽然模运算不如(例如)加法有效,但我发现很难相信它比条件分支慢很多。不管怎样,你的编译器应该足够聪明,可以根据需要将任何一个版本转换成另一个版本。那里没有分支。它被编译成执行逐位操作的CPU指令,因此,我不相信编译器会理解第二个模运算可以被消除,因为它需要对实际的算术进行推理(例如,除非专门添加了适当的优化规则来处理这种形式的表达式,否则不会发生)@尤尼尔:现在的编译器相当聪明。我怀疑它会将每个模分解为“如果股息为正”和“如果股息为负”两种情况,并分别进行分析。这是我在五分钟内想到的一个明显的窥视孔优化。编译器编写人员肯定知道这一点。