[英]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
。
因此,采用模量会导致负面结果。
这里有两件事在起作用。
int
相乘可以得到一个大于Integer.MAX_VALUE
(2147483647)的数字,该数字会回绕为负数。 您需要考虑如何在给定大小写值(例如非常大的整数或负数)的情况下使用此函数。
例如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
? 毫无疑问,有很多方法可以生成数字。 我建议使用更具体的名称。
参数randomNo
和value
也有问题。 为什么第一个参数是否随机, 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.