99

我做模数错了吗?因为在 Java 中-13 % 64评估为-13但我想得到51.

4

14 回答 14

106

负数模数的两种定义都在使用——一些语言使用一种定义,另一些使用另一种定义。

如果你想得到一个负输入的负数,那么你可以使用这个:

int r = x % n;
if (r > 0 && x < 0)
{
    r -= n;
}

同样,如果您使用的语言在负输入上返回负数并且您更喜欢正数:

int r = x % n;
if (r < 0)
{
    r += n;
}
于 2010-12-09T22:00:02.213 回答
74

由于“数学上”两者都是正确的:

-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

于 2010-12-09T21:58:53.527 回答
20

您确定您正在使用 Java 工作吗?因为Java按预期给出了-13 % 64 = -13。分红的标志!

于 2011-01-09T10:44:41.623 回答
15

您的结果对于 Java 是错误的。请提供一些背景信息(您的程序、实现和 Java 版本)。

来自Java 语言规范

15.17.3 余数运算符 %
[...]
在二进制数字提升(第 5.6.2 节)之后,整数操作数的余数运算产生一个结果值,使得 (a/b)*b+(a%b) 等于一个。
15.17.2 除法运算符 /
[...]
整数除法向 0 舍入。

由于 / 向零舍入(结果为零),因此在这种情况下 % 的结果应该是负数。

于 2010-12-10T20:34:37.380 回答
6

您可以使用

(x % n) - (x < 0 ? n : 0);
于 2010-12-09T22:05:36.437 回答
3

你的答案在维基百科: 模运算

它说,在 Java 中,模运算的符号与除数相同。并且由于我们谈论的是除法运算的其余部分,所以它在您的情况下返回-13,因为-13/64 = 0。-13-0 = -13。

编辑:对不起,误解了你的问题......你是对的,java应该给-13。你能提供更多的周边代码吗?

于 2010-12-09T22:06:02.920 回答
2

具有负操作数的模运算由语言设计者定义,他们可能会将其留给语言实现,他们可能会将定义推迟到 CPU 体系结构。

我找不到 Java 语言定义。
感谢 Ishtar,余数运算符 %的 Java 语言规范说结果的符号与分子的符号相同。

于 2010-12-09T22:02:24.513 回答
1

mod 函数定义为一个数超过不大于该数的除数的最大整数倍的量。所以在你的情况下

-13 % 64

不超过 -13 的 64 的最大整数倍数是 -64。现在,当你从 -64 中减去 -13 时,它等于 51-13 - (-64) = -13 + 64 = 51

于 2010-12-09T22:09:56.160 回答
1

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

于 2010-12-09T22:02:38.173 回答
1

为了克服这个问题,您可以将64(或任何您的模数基数)添加到负值,直到它为正

int k = -13;
int modbase = 64;

while (k < 0) {
    k += modbase;
}

int result = k % modbase;

结果仍将在同一个等价类中。

于 2010-12-09T22:07:19.030 回答
0

在我的 Java JDK 1.8.0_05 版本中 -13%64=-13

您可以尝试 -13-(int(-13/64)) 换句话说,将除法转换为整数以摆脱小数部分,然后从分子中减去因此 numerator-(int(numerator/denominator)) 应该给出正确的余数和符号

于 2015-03-12T02:00:14.040 回答
0

根据 JLS 的第 15.17.3 节,“在二进制数字提升之后,整数操作数的余数运算会产生一个结果值,使得 (a/b)*b+(a%b) 等于 a。这个恒等式甚至在特殊情况下,被除数是其类型的最大可能幅度的负整数,除数是 -1(余数是 0)。

希望有帮助。

于 2016-04-14T14:09:42.580 回答
0

在 Java 最新版本中,您将获得-13%64 = -13. 答案总是有分子的符号。

于 2015-09-23T14:40:42.847 回答
-1

在这种情况下,我认为 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);
    }
}
于 2014-06-23T15:15:32.690 回答