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指令,因此,我不相信编译器会理解第二个模运算可以被消除,因为它需要对实际的算术进行推理(例如,除非专门添加了适当的优化规则来处理这种形式的表达式,否则不会发生)@尤尼尔:现在的编译器相当聪明。我怀疑它会将每个模分解为“如果股息为正”和“如果股息为负”两种情况,并分别进行分析。这是我在五分钟内想到的一个明显的窥视孔优化。编译器编写人员肯定知道这一点。