今天看了一眼java.lang.Integer类的源码,发现了这么一句话:
// really: r = i - (q * 100);
r = i - ((q << 6) + (q << 5) + (q << 2));
乍看之下不懂啊。不过还好有上面那一句注释。
好,来研究研究,我们知道,移位操作是直接操作的二进制数据,那么为什么
((q << 6) + (q << 5) + (q << 2))
这么移一下位就变成和 q * 100一样的效果了呢。
我们来看看100这个数字的二进制是多少:1100100
总共7位,嗯。来,我们将之分离开来成为:
1000000
0100000
0000000
0000000
0000100
0000000
0000000
这七组数据相加就是100,对吧?
好,1<<6 就是1000000,1<<5就是100000,同理1<<2就是100,其它为0的位置,我们怎么移都是0,所以不管了。
然后,我们 (1 << 6) + (1 <<5) + (1 << 2)就是100,得出来这个结果了吗?
这个原理试用于所有正整数(负数及浮点数未测试)
好了,先原谅我没学过计算机组成原理,操作系统神马的。
从网上的资料和老师说的,都是说CPU没有乘法运算指令的,都是用加法指令代替乘法运算。
所以移位运算应该会比乘法运算效率高。
下面我举得例子不知道正确否,但是确实结果出了我的意料之外。
int num = 65536;
int res1 = 0;
int res2 = 0;
long start1 = System.currentTimeMillis();
for(int i = 0; i < Integer.MAX_VALUE; i++){
res1 = (65536 << 7) + (65536 << 3) + (65536 << 1) + (65536 << 0); // 实际上是 num * 139
}
long time1 = System.currentTimeMillis() - start1;
long start2 = System.currentTimeMillis();
for(int i = 0; i < Integer.MAX_VALUE; i++){
res2 = 65536 * 139;
}
long time2 = System.currentTimeMillis() - start2;
System.out.println(" time1:" + time1 + " \t res1:" + res1);
System.out.println(" time2:" + time2 + " \t res2:" + res2);
直接使用常量来计算,在这个例子中移位运算和乘法运算效率相差无几。
但是如果将算式中的65536换成 num变量的话,就会发现乘法运算的效率会比移位运算快。而且是2-3倍。
常量运算结果:
变量运算结果:
期待高手解释一下,感激不尽。