繁体   English   中英

Java MOD运算符返回负值

[英]Java MOD operator returns negative value

我有这种方法:

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

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

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

谁能解释一下。

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

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

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

例如:

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

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

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

或更详细地说,乘积的位是“全”乘积的最低32位(两个32位整数的全积为64位),当然,如果我们只需要那些位(或一些)子集,例如最低的8),那就很好了。 但是,如果我们想要的结果取决于乘积的32个高位,那么显然我们将需要计算这些位。 (x * y) MOD p其中p不是2的幂)将取决于整个乘积的所有位。

17719*197920 = 3506944480 ,该值大于Integer.MAX_VALUE

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

因此,采用模量会导致负面结果。

这里有两件事在起作用。

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

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

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

您可能需要在做模之前确保您的值是正的,如下所示:

Math.abs(randomNo * value) % 256

但是,这实际上有一个非常有趣的Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE情况,其中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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM