我做模数错了吗?因为在 Java 中-13 % 64
评估为-13
但我想得到51
.
14 回答
负数模数的两种定义都在使用——一些语言使用一种定义,另一些使用另一种定义。
如果你想得到一个负输入的负数,那么你可以使用这个:
int r = x % n;
if (r > 0 && x < 0)
{
r -= n;
}
同样,如果您使用的语言在负输入上返回负数并且您更喜欢正数:
int r = x % n;
if (r < 0)
{
r += n;
}
由于“数学上”两者都是正确的:
-13 % 64 = -13 (on modulus 64)
-13 % 64 = 51 (on modulus 64)
Java 语言开发人员必须选择其中一个选项,他们选择了:
结果的符号等于被除数的符号。
在 Java 规范中这样说:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.3
您确定您正在使用 Java 工作吗?因为Java按预期给出了-13 % 64 = -13。分红的标志!
您的结果对于 Java 是错误的。请提供一些背景信息(您的程序、实现和 Java 版本)。
15.17.3 余数运算符 %
[...]
在二进制数字提升(第 5.6.2 节)之后,整数操作数的余数运算产生一个结果值,使得 (a/b)*b+(a%b) 等于一个。
15.17.2 除法运算符 /
[...]
整数除法向 0 舍入。
由于 / 向零舍入(结果为零),因此在这种情况下 % 的结果应该是负数。
您可以使用
(x % n) - (x < 0 ? n : 0);
你的答案在维基百科: 模运算
它说,在 Java 中,模运算的符号与除数相同。并且由于我们谈论的是除法运算的其余部分,所以它在您的情况下返回-13,因为-13/64 = 0。-13-0 = -13。
编辑:对不起,误解了你的问题......你是对的,java应该给-13。你能提供更多的周边代码吗?
具有负操作数的模运算由语言设计者定义,他们可能会将其留给语言实现,他们可能会将定义推迟到 CPU 体系结构。
我找不到 Java 语言定义。
感谢 Ishtar,余数运算符 %的 Java 语言规范说结果的符号与分子的符号相同。
mod 函数定义为一个数超过不大于该数的除数的最大整数倍的量。所以在你的情况下
-13 % 64
不超过 -13 的 64 的最大整数倍数是 -64。现在,当你从 -64 中减去 -13 时,它等于 51-13 - (-64) = -13 + 64 = 51
x = x + m = x - m
在模数中m
。
所以-13 = -13 + 64
在模数64
和-13 = 51
模数中64
。
假设Z = X * d + r
,如果0 < r < X
然后在除法中,Z/X
我们称r
余数。
Z % X
返回 的余数Z/X
。
为了克服这个问题,您可以将64
(或任何您的模数基数)添加到负值,直到它为正
int k = -13;
int modbase = 64;
while (k < 0) {
k += modbase;
}
int result = k % modbase;
结果仍将在同一个等价类中。
在我的 Java JDK 1.8.0_05 版本中 -13%64=-13
您可以尝试 -13-(int(-13/64)) 换句话说,将除法转换为整数以摆脱小数部分,然后从分子中减去因此 numerator-(int(numerator/denominator)) 应该给出正确的余数和符号
根据 JLS 的第 15.17.3 节,“在二进制数字提升之后,整数操作数的余数运算会产生一个结果值,使得 (a/b)*b+(a%b) 等于 a。这个恒等式甚至在特殊情况下,被除数是其类型的最大可能幅度的负整数,除数是 -1(余数是 0)。
希望有帮助。
在 Java 最新版本中,您将获得-13%64 = -13
. 答案总是有分子的符号。
在这种情况下,我认为 Java 不会返回 51。我在 Mac 上运行 Java 8,我得到:
-13 % 64 = -13
程序:
public class Test {
public static void main(String[] args) {
int i = -13;
int j = 64;
System.out.println(i % j);
}
}