转载自:http://blog.csdn.net/tingting256/article/details/52550188
常见位操作
需要熟练掌握一些常见功能的位操作实现,具体为:
<1> 常用的等式:-n = ~(n-1) = ~n+1
<2> 获取整数n的二进制中最后一个1:n&(-n) 或者 n&~(n-1),如:n=010100,则-n=101100,n&(-n)=000100
<3> 去掉整数n的二进制中最后一个1:n&(n-1),如:n=010100,n-1=010011,n&(n-1)=010000
二进制加法
可以很容易地用“异或”和“或”操作实现整数加法运算:对应位数的“异或操作”可得到该位的数值,对应位的“与操作”可得到该位产生的高位进位。循环相加,直到没有进位就可以得到结果。
如:a=010010,b=100111,计算步骤如下:
第一轮:a^b=110101,(a&b)<<1=000100, 由于进位(000100)大于0,则进入下一轮计算,a=110101,b=000100,a^b=110001,(a&b)<<1=001000,由于进位大于0,则进入下一轮计算:a=110001,b=001000,a^b=111001,(a&b)<<1=0,进位为0,终止,计算结果为:111001。
二进制减法
可以转化为二进制加法
减法可很容易地转化为加法:a - b = a + (-b) = a + (~b + 1 )
二进制乘法
先看一个实例:1011*1010:
1011
* 1010
----------
10110 < 左移一位,乘以0010
+ 1011000 < 左移3位,乘以1000
----------
1101110
因而乘法可以通过系列移位和加法完成。最后一个1可通过b&~(b-1)求得,可通过b& (b-1)去掉,为了高效地得到左移的位数,可提前计算一个map。
二进制除法
使用移位运算和加减相结合
例如:求101011除以11:
在上图的除法过程中:
(1)第一次除法先找到除数应该左移的位数,使得除数是不大于除数的数,上图中将除数左移了三位(11<< 3 = 11000),变为11000;然后本次除法结果为(1 << 3);被除数变为了原来的被除数101011 减去当前的除数11000:10011,该被除数就是下一次除法的被除数。
(2)第二次除法的被除数为10011,此次的除数为上一次除法右移一位,即(原始除数11左移两位:11<<2 = 1100);本次除法结果为(1<<2);被除数变为10011 - 1100 = 111,这作为下一次除法的被除数。
(3)第三次除法的被除数变为111,除数是上一次除法右移一位,也就是初始除数11左移一位(11<< 1 = 110);本次除法结果为(1<<1);被除数为111 - 110 = 1;
(4)乘法结束。商为(1 << 3 + 1 << 2 + 1 << 1) = 1000 + 100 + 10 = 1110 = 14。
源代码
- import java.util.HashMap;
- import java.util.Map;
-
- public class Binary {
- public static void main(String args[])
- {
- int a=20;
- int b=5;
- System.out.println(myAdd(a,b));
- System.out.println(mySub(a,-b));
- System.out.println(myMuti(a,b));
- System.out.println(myDiv(a,b));
- System.out.println(myDiv(a,-b));
- }
-
- public static int myAdd(int a,int b)
- {
- int sum;
- int carry;
- do
- {
- sum=a^b;
- carry=(a&b)<<1;
- a=sum;
- b=carry;
- }while(carry!=0);
- return sum;
- }
-
- public static int mySub(int a,int b)
- {
- return myAdd(a,myAdd(~b,1));
- }
-
- public static long myMuti(int a,int b)
- {
- boolean flag=(b<0);
- if(flag) b=-b;
- Map<Integer,Integer> map=new HashMap<Integer,Integer>();
- for(int i=0;i<32;i++)
- {
- map.put(1<<i, i);
- }
- int sum=0;
- while(b>0)
- {
- int last=b&(~b+1);
- int count=map.get(last);
- sum+=a<<count;
- b=b&(b-1);
- }
- if(flag) sum=-sum;
- return sum;
- }
-
- public static int myDiv(int a,int b)
- {
- boolean flag=(a<0)^(b<0);
- if(a<0) a=-a;
- if(b<0) b=-b;
- if(a<b) return 0;
- int msb=0;
- while((b<<msb)<a)
- {
- msb++;
- }
- int q=0;
- for(int i=msb;i>=0;i--)
- {
- if((b<<i)>a) continue;
- q|=(1<<i);
- a-=(b<<i);
- }
- if(flag) return -q;
- return q;
- }
- }