对于 JAVA 编程中,适当的采用位移运算,会减少代码的运行时间,提高项目的运行效率。这个可以从一道面试题说起:
问题:
答案:2 << 3
由此就引发了我的思考,为什么位移运算会比乘法运算更快呢?其实简单的想想,计算机的内存是用由 0 和 1 组成的二进制数据形式来表示数据的,对于乘法运算,我想内部应该还会转化成位移运算。
下面用一个例子来验证上面的正确性。
例子:
public class Demo2 { public static void main(String[] args){ Demo2 d = new Demo2(); d.method1(); d.method2(); } public void method1(){ long start = System.nanoTime(); int i = 100; int j = i*2; System.out.println("乘法运算耗时:"+(System.nanoTime()-start)); } public void method2(){ long start = System.nanoTime(); int i = 100; int j = i<<1; System.out.println("位移运算耗时:"+(System.nanoTime()-start)); } }
输出:
乘法运算耗时 :46114 (单位纳秒)
位移运算耗时 :8016 (单位纳秒)
同时我简化上面的代码:
public class Demo2 { public void method1(){ int i = 100; int j = i*2; } public void method2(){ int i = 100; int j = i<<1; } }
E:\>javac Demo2.java
E:\>javap -verbose Demo2 >> Demo.txt
查询字节码信息:
…… public void method1(); Code: Stack=2, Locals=3, Args_size=1 0: bipush 100 2: istore_1 3: iload_1 4: iconst_2 5: imul 6: istore_2 7: return LineNumberTable: line 7: 0 line 8: 3 line 9: 7 public void method2(); Code: Stack=2, Locals=3, Args_size=1 0: bipush 100 2: istore_1 3: iload_1 4: iconst_1 5: ishl 6: istore_2 7: return LineNumberTable: line 12: 0 line 13: 3 line 14: 7 }
从区别来看,位移运算调的是 ishl (将 int 型数值左移位指定位数并将结果压入栈顶)指令,乘法运算调的是 imul (将栈顶两 int 型数值相乘并将结果压入栈顶)指令。
整数乘法或整数除法所需要的时钟周期远远大于移位操作所需的时钟周期,下面列出这个指令的基本执行时间:
移位指令 寄存器移 1 位 时钟周期数为 2
整数乘法 IMUL 16 位寄存器乘 时钟周期为 128 ~ 154
整数除法 IDIV 16 位寄存器 时钟周期为 165 ~ 184
如果再要深究为什么,就要研究寄存器和电路图了的知识了 … 点到为止 ..
参考资料:
http://www.programfan.com/blog/article.asp?id=32217
http://blog.csdn.net/kypfos/article/details/810151
http://budairenqin.iteye.com/blog/1565750