在java中,当你做
a % b
如果a为负数,它将返回负数结果,而不是像应该包裹到b那样。解决此问题的最佳方法是什么?我认为唯一的方法是
a < 0 ? b + a : a % b
在java中,当你做
a % b
如果a为负数,它将返回负数结果,而不是像应该包裹到b那样。解决此问题的最佳方法是什么?我认为唯一的方法是
a < 0 ? b + a : a % b
Answers:
它的行为应为%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
)。
a < 0
,也许您可以看看)
(a % b + b) % b
,对于a
和很大的值,它会分解b
。例如,使用a = Integer.MAX_VALUE - 1
和b = Integer.MAX_VALUE
将给出-3
结果,这是一个负数,这是您要避免的。
while
如果确实需要@Mikepote,则使用a的速度会较慢,除非只需要使用a ,否则if
实际上会更快。
从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
参数。Mod二进制运算符(%
)也可用于float
和double
操作数。
对于尚未使用(或无法使用)Java 8的用户,Guava借助IntMath.mod()进行了抢救,该工具自Guava 11.0起可用。
IntMath.mod( 2, 3) = 2
IntMath.mod(-2, 3) = 1
一个警告:与Java 8的Math.floorMod()不同,除数(第二个参数)不能为负。
在数论中,结果总是正的。我猜想在计算机语言中并非总是如此,因为并非所有程序员都是数学家。我的两分钱,我会认为它是该语言的设计缺陷,但您现在不能更改。
= MOD(-4,180)= 176 = MOD(176,180)= 176
因为180 *(-1)+ 176 = -4与180 * 0 + 176 = 176相同
使用此处的时钟示例http://mathworld.wolfram.com/Congruence.html ,即使两个答案都满足基本方程式,您也不会说duration_of_time mod cycle_length是-45分钟,而是15分钟。
-1
而不是n-1
)然后就可以了。
Java 8具有Math.floorMod
,但是它非常慢(其实现具有多个除法,乘法和有条件的)。但是,JVM可能具有针对其进行内部优化的存根,这将显着提高其速度。
没有此操作的最快方法与floorMod
此处的其他答案类似,但没有条件分支,只有一个慢%
操作。
假设n为正,并且x可以是任何值:
int 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
而不是确切的mod运算符,并且您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
这可能会或可能不会比其他公式[(a%b + b)%b]快。与其他公式不同,它包含一个分支,但是使用较少的取模运算。如果计算机可以正确预测<0,则可能是一场胜利。
(编辑:修正了公式。)