我知道modulus operation可以使用一点 & 明智的魔法进行优化,其中除数是2的幂...
答案 0 :(得分:3)
是的,使用x % pow(2, n)
x & ((1 << n) - 1)
但是如果x是负数,那么java中的%-operator可以给出不同的结果,所以盲目地用一个代替另一个可能会破坏代码。
当位寻址,屏蔽等通常使用&amp; -variant时,因为它在语义上更接近于汇编程序/ C和签名中使用的内容,在这种情况下通常不需要/关心。
至于如果JIT将%优化为&amp;,答案是:它完全取决于JIT - 那就是一个移动的目标。
如果x % y
其中y不是常数,如果y是2的幂,则非常难以检测到,因此可能该情况不可优化,因为检测它非常困难或不可能。如果y是常数,则JIT仍然证明x不是负数 - 或者插入类似于result = x < 0 ? x % y : x & (y-1)
的条件。它可能会也可能不会这样,取决于所讨论的JIT,也取决于平台。至少Hotspot在某些情况下对不同的处理器(同一个ISA,即AMD vs Intel)使用不同的优化。
答案 1 :(得分:2)
我在这个问题上花了一些时间,用blog post写下所有细节。
简而言之:
irem
(mod int)比n & (pow2-1)
技巧慢〜20%frem
(mod浮动)慢3倍因此,对双打不做mod
有明显的好处,你可以通过自然整数红利和2除数的力量获得一些好处。
答案 2 :(得分:-1)
以下是一个示例代码段
public class Test {
public static void main(String[] args) {
int a=103;
int b=5;
int c=a%b;
}
}
现在,如果您看到它的编译代码,您将看到
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: bipush 103
2: istore_1
3: iconst_5
4: istore_2
5: iload_1
6: iload_2
7: irem
8: istore_3
9: return
bipush-将一个字节作为整数值(即103
)推入堆栈istore_1 - 从堆栈中弹出一个int并将其存储在当前帧的本地变量中。
和3:iconst_5常量整数被压入堆栈
istore_2与istore_1相同,只是名为changed的变量。
然后5: iload_1
和6:iload_2
两个变量再次被压入堆栈以进行操作
now at 7:irem the remainder operator works which you are calling as modulo.
现在Remainder运算符是如何工作的。它从操作数堆栈中弹出两个整数(a和b的值),除以b,计算余数并将int余数推回堆栈。其余的是(b - ((a / b)* b))。这是Java中%运算符使用的内容。