加法运算
原理:
两个数相加,可以拆分为两个数每一位分别相加,并且不进位的结果,再加上进位。
简单举个例子,比如 14+7= 11+10 =21
11 就是不进位相加的结果,换句话就是两个数个位与个位相加,十位与十位相加,并且不进位(个位相加并且不进位为1,十位相加为1,所以为11)
10就是进位 7+4>=10 所以要进位10
再举个例子134+968 = 092+1010 = 1002+100 = 1102+0 =1102
不难发现,进位会随着重复求和而不断变小,直到为0(也就是两个数相加没有发生进位)
int bit_add(int a,int b){
int resu=a^b;
int more=(a&b)<<1;
while(more){
a=resu;
resu=resu^more;
more=(a&more)<<1;
}
return resu;
}
减法运算
原理:
a-b=a+(-b)
所以关键就是把减数换成负数。
求一下b的补码就行:先求b的反码再加1,就是补码
int bit_subtract(int a, int b){
return bit_add(a,bit_add((~b),1));
}
乘法运算
原理:
依旧基于加法运算
a*b=b个a相加
a,b同号为正,异号为负
int bit_multi1(int a ,int b){
if(abs(a)<abs(b)) swap(a,b);
int aa=abs(a),bb=abs(b),resu=0;
while(bb--){
resu=bit_add(resu,aa);
}
if((a^b)<0)
return bit_add((~resu),1);
return resu;
}
//如果要求比较严格,要把求绝对值换成取补码的形式。
上面算法在数据较大时候效率太低。
优化算法:
将a,b换成二进制后,用竖式模拟计算
还是举个简单的例子会稍微明白点:
如:
12*5 =>
1100
* 101
--------
1100
0000
+ 1100
----------
111100
=60
int bit_multi2(int a,int b){
int aa=abs(a),bb=abs(b),resu=0;
while(bb){
if(bb&0x1){
resu=bit_add(resu,aa);
}
aa=aa<<1;
bb=bb>>1;
}
if((a ^ b) < 0)
return bit_add((~resu),1);
return resu;
}
除法运算
原理:
每次减一个b,直到a
int bit_divi(int a,int b){
int aa=abs(a),bb=abs(b),resu=0;
while(aa>=bb){
aa=bit_subtract(aa,bb);
resu++;
}
if((a ^ b) < 0)
return bit_add((~resu),1);
return resu;
}
当a-b很大时候(如:23123/1)那么上面算法十分没有效率。
优化算法:
每次不去减b,改为减去最大能减去的。
考虑到Int范围不超过2^31所以就从31以递减的顺序看a最大能减几。
int bit_divi2(int a,int b){
int aa=abs(a),bb=abs(b),resu=0;
for(int i=31;i>=0;i--){
while((aa>>i) >=bb){
aa=bit_subtract(aa,bb<<i);
resu=bit_add(resu,1<<i);
}
}
if((a ^ b) < 0)
return bit_add((~resu),1);
return resu;
}
全部代码
//+
int bit_add(int a,int b){
int resu=a^b;
int more=(a&b)<<1;
while(more){
a=resu;
resu=resu^more;
more=(a&more)<<1;
}
return resu;
}
//-
int bit_subtract(int a, int b){
return bit_add(a,bit_add((~b),1));
}
//*1
int bit_multi1(int a ,int b){
if(abs(a)<abs(b)) swap(a,b);
int aa=abs(a),bb=abs(b),resu=0;
while(bb--){
resu=bit_add(resu,aa);
}
if((a^b)<0)
return bit_add((~resu),1);
return resu;
}
//*2
int bit_multi2(int a,int b){
int aa=abs(a),bb=abs(b),resu=0;
while(bb){
if(bb&0x1){
resu=bit_add(resu,aa);
}
aa=aa<<1;
bb=bb>>1;
}
if((a ^ b) < 0)
return bit_add((~resu),1);
return resu;
}
///1
int bit_divi1(int a,int b){
int aa=abs(a),bb=abs(b),resu=0;
while(aa>=bb){
aa=bit_subtract(aa,bb);
resu=bit_add(resu,1);
}
if((a ^ b) < 0)
return bit_add((~resu),1);
return resu;
}
///2
int bit_divi2(int a,int b){
int aa=abs(a),bb=abs(b),resu=0;
for(int i=31;i>=0;i--){
while((aa>>i) >=bb){
aa=bit_subtract(aa,bb<<i);
resu=bit_add(resu,1<<i);
}
}
if((a ^ b) < 0)
return bit_add((~resu),1);
return resu;
}
int main()
{
int a,b;
while(cin>>a>>b){
cout<<bit_add(a,b)<<endl;
cout<<bit_subtract(a,b)<<endl;
cout<<bit_multi1(a,b)<<endl;
cout<<bit_multi2(a,b)<<endl;
cout<<bit_divi1(a,b)<<endl;
cout<<bit_divi2(a,b)<<endl;
}
return 0;
}