在Java中,当你执行以下操作时:
a % b
如果a是负数,它将返回一个负结果,而不是像应该一样回绕到b。修复这个问题的最佳方法是什么?我唯一能想到的方法是什么。如果a是负数,则结果将变为负数,而不是像应该一样绕到b。如何修复这个问题?我所能想到的唯一方法是:
a < 0 ? b + a : a % b
在Java中,当你执行以下操作时:
a % b
如果a是负数,它将返回一个负结果,而不是像应该一样回绕到b。修复这个问题的最佳方法是什么?我唯一能想到的方法是什么。a < 0 ? b + a : a % b
a % b = a - a / b * b
,也就是余数。(a % b + b) % b
。
这个表达式的作用是,(a % b)
的结果一定小于 b
,无论 a
是正数还是负数。添加 b
可以处理 a
的负值,因为 (a % b)
是介于 -b
和 0
之间的负值,(a % b + b)
一定小于 b
并且为正数。最后一个模数是为了防止 a
最初就是正数,因为如果 a
是正数,则 (a % b + b)
将变得大于 b
。因此,(a % b + b) % b
再次将其转换为小于 b
(并不影响负的 a
值)。
(a % b)
的结果一定小于b
(无论a
是正数还是负数),加上b
可以处理a
的负值,因为(a % b)
小于b
且小于0
,所以(a % b + b)
一定小于b
并且为正数。最后一个模数运算是为了处理a
最初是正数的情况,因为如果a
是正数,则(a % b + b)
会变大超过b
。因此,(a % b + b) % b
将其再次变成小于b
的值(不影响负的a
值)。 - ethanfara < 0
进行了轻微更正,也许您可以看一下)。 - Maarten Bodewes(a%b + b)%b
会失效。
例如,使用 a = Integer.MAX_VALUE - 1
和 b = Integer.MAX_VALUE
将会得到 -3
作为结果,这是一个负数,而这正是您想要避免的。 - Thorbearwhile
会更慢,除非你只需要一个 if
,在这种情况下它实际上会更快。 - Peter Lawrey从Java 8开始,你可以使用Math.floorMod(int x, int y)和Math.floorMod(long x, long y)。这两个方法返回与Peter的答案相同的结果。
Math.floorMod( 2, 3) = 2
Math.floorMod(-2, 3) = 1
Math.floorMod( 2, -3) = -1
Math.floorMod(-2, -3) = -2
float
或double
参数。 取模二元运算符(%
)也适用于float
和double
操作数。 - Mir-Ismaili对于那些尚未使用(或无法使用)Java 8的人,Guava通过IntMath.mod()在Guava 11.0版本中提供了救济。
IntMath.mod( 2, 3) = 2
IntMath.mod(-2, 3) = 1
需要注意的是:与Java 8的Math.floorMod()不同,除数(第二个参数)不能为负数。
-1
而不是n-1
),那么就可以使用它。 - BeUndeadint remainder = (x % n); // may be negative if x is negative
//if remainder is negative, adds n, otherwise adds 0
return ((remainder >> 31) & n) + remainder;
n = 3
时,结果为:x | result
----------
-4| 2
-3| 0
-2| 1
-1| 2
0| 0
1| 1
2| 2
3| 0
4| 1
0
和 n-1
之间进行均匀分布,而不需要确切的模运算,并且你的 x
不会靠近 0
,那么以下方法会更快,因为有更多的指令级并行性,在计算慢速的 %
时,其他部分可以和它并行执行,因为它们不依赖于其结果。
return ((x >> 31) & (n - 1)) + (x % n)
以下是 n=3
时上述代码的结果:x | result
----------
-5| 0
-4| 1
-3| 2
-2| 0
-1| 1
0| 0
1| 1
2| 2
3| 0
4| 1
5| 2
如果输入是int类型的完整范围内的随机数,那么两个解决方案的分布将相同。如果输入接近零,则后一个解决方案中在 n - 1
处会有太少的结果。
这里有一个替代方案:
a < 0 ? b-1 - (-a-1) % b : a % b
使用floorMod方法是最好的选择。
我很惊讶没有人提到显而易见的事。
Math.abs(a) % b
floorMod(-1, 4) ==> 3
,但 Math.abs(-1) % 4 ==> 1
。 - just-max