Java MOD运算符返回负值

时间:2018-11-11 21:03:09

标签: java negative-number mod

我有这种方法:

private static int generateNo(int randomNo, int value){
    return   ((randomNo*value)%256);
}

在我的例子中  randomNo = 17719  qValue = 197920

当我用计算器计算时,返回值应该为224,但是,当我运行程序时,它返回-32。

任何人都可以解释一下。

4 个答案:

答案 0 :(得分:2)

一些提示。如果您在将数字相乘(或相加)时遇到意外的负值,则主要是数字溢出:

private static int generateNo(int randomNo, int value) {
    return (int)(((long)randomNo * value) % 256);
}

答案 1 :(得分:2)

Java习惯于使用有符号余数而不是通常指模数(欧几里得除法的非负余数)的运算。幸运的是,对于2的幂,有一个非常简单的解决方法:使用按位&。无论如何,这比较容易想到,因为它是对位的微不足道的操作,而不是复杂的除法算法的结果。

例如:

private static int generateNo(int randomNo, int value) {
    return randomNo * value & 255;
}

由于& 255保证只能设置结果的低8位,因此结果不可能为负。因此,结果肯定在[0..255]范围内。

如果您想要结果的一些低位(例如最低的8位),请先保留乘法换行。如果您想计算(x * y) MOD p不是2的幂的情况下,它将无法正常工作,因为这样(在解决Java的带符号余数之后),实际的计算就变成了(由于包装){{ 1}}。 IFF p除以2³²(即,如果((x * y) MOD 2³²) MOD p是不超过2³²的2的幂)然后可简化为p

或者具有更高的位级别视图:乘积的位是“全”乘积的最低32位(两个32位整数的全积具有64位),当然,如果我们只需要这些位(或其中的一些子集,例如最低的8个),就可以了。但是,如果我们想要的结果取决于乘积的32个高位,那么显然我们将需要计算这些位。 p的{​​{1}}不是2的幂将取决于整个乘积的所有位。

答案 2 :(得分:1)

17719*197920 = 3506944480,它比Integer.MAX_VALUE大。

这样,乘法会使int的范围溢出,结果为-788022816

因此,取模数会得出负结果。

答案 3 :(得分:1)

这里有两件事在玩。

  1. 将两个int相乘可以得到一个大于Integer.MAX_VALUE(2147483647)的数字,该数字会转为负数。
  2. 将模运算符应用于正数和负数会导致负数。

您需要考虑如何在给定大小写值(例如非常大的整数或负数)的情况下使用此功能。

例如generateNo(-100, 50)应该产生什么?

您可能希望在进行模数运算之前确保您的值是正数,

Math.abs(randomNo * value) % 256

但是,这实际上有一个非常有趣的极端情况,其中Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE因为溢出。

相反,请在结果上使用Math.abs

Math.abs((randomNo * value) % 256)

我还将对此功能进行一些一般性的评论。名称并不能真正解释其作用。为什么generateNo?毫无疑问,有很多方法可以生成数字。我建议使用更具体的名称。

参数randomNovalue也是有问题的。为什么generateNo关心第一个参数是否为随机数?

更清楚地指定要发生的事情,并使用名称来描述这些事情,可能会更容易思考。

当出现类似问题时,我还建议分解步骤,以便您了解发生了什么。像这样:

private static int generateNo(int randomNo, int value){
    final int product = randomNo * value;
    final int result = product % 256;

    // Breakpoint or System.out.println here, to understand the values...
    return result;
}