用位运算实现四则运算之加减乘除

转自:http://blog.csdn.net/hackbuteer1/article/details/7390093

听同学百度二面中,不准用四则运算操作符来实现四则运算。一想就想到了计算机组成原理上学过的。位运算的思想可以应用到很多地方,这里简单的总结一下用位运算来实现整数的四则运算。

加法运算:

[cpp]  view plain copy
  1. int AddWithoutArithmetic(int num1,int num2)  
  2. {  
  3.     if(num2==0) return num1;//没有进位的时候完成运算  
  4.     int sum,carry;  
  5.     sum=num1^num2;//完成第一步没有进位的加法运算  
  6.     carry=(num1&num2)<<1;//完成第二步进位并且左移运算  
  7.     return AddWithoutArithmetic(sum,carry);//进行递归,相加  
  8. }  

简化一下:

[cpp]  view plain copy
  1. int Add(int a,int b)  
  2. {  
  3.     return b ? Add(a^b,(a&b)<<1) : a;  
  4.     /*if(b) 
  5.         return Add(a^b,(a&b)<<1); 
  6.     else 
  7.         return a;*/  
  8. }  

上面的思路就是先不计进位相加,然后再与进位相加,随着递归,进位会变为0,递归结束。 

非递归的版本如下:

[cpp]  view plain copy
  1. int Add(int a, int b)  
  2. {  
  3.     int ans;  
  4.     while(b)  
  5.     {   //直到没有进位  
  6.         ans = a^b;        //不带进位加法  
  7.         b = ((a&b)<<1);   //进位  
  8.         a = ans;  
  9.     }  
  10.     return a;  
  11. }   

减法运算:

[cpp]  view plain copy
  1. //这个和加法一样了,首先取减数的补码,然后相加。  
  2. int negtive(int a)   //取补码  
  3. {  
  4.     return Add(~a, 1);  
  5. }  
  6. int Sub(int a, int b)  
  7. {  
  8.     return Add(a, negtive(b));  
  9. }   

正数乘法运算:

[cpp]  view plain copy
  1. //正数乘法运算  
  2. int Pos_Multiply(int a,int b)  
  3. {  
  4.     int ans = 0;  
  5.     while(b)  
  6.     {  
  7.         if(b&1)  
  8.             ans = Add(ans, a);  
  9.         a = (a<<1);  
  10.         b = (b>>1);  
  11.     }  
  12.     return ans;  
  13. }  

整数除法(正整数)

[cpp]  view plain copy
  1. //除法就是由乘法的过程逆推,依次减掉(如果x够减的)y^(2^31),y^(2^30),...y^8,y^4,y^2,y^1。减掉相应数量的y就在结果加上相应的数量。  
  2. int Pos_Div(int x,int y)  
  3. {  
  4.     int ans=0;  
  5.     for(int i=31;i>=0;i--)  
  6.     {  
  7.         //比较x是否大于y的(1<<i)次方,避免将x与(y<<i)比较,因为不确定y的(1<<i)次方是否溢出  
  8.         if((x>>i)>=y)  
  9.         {  
  10.             ans+=(1<<i);  
  11.             x-=(y<<i);  
  12.         }  
  13.     }  
  14.     return ans;  
  15. }  

完整的实现:

[cpp]  view plain copy
  1. // 加减乘除位运算   
  2. // 程序中实现了比较大小、加减乘除运算。所有运算都用位操作实现   
  3. // 在实现除法运算时,用了从高位到低位的减法   
  4. // 具体如下,算法也比较简单,所以没有作注释  
  5. #include<iostream>  
  6. #include<cstdio>  
  7. using namespace std;  
  8.   
  9. int Add(int a, int b)  
  10. {  
  11.     int ans;  
  12.     while(b)  
  13.     {  //直到没有进位  
  14.         ans = a^b;        //不带进位加法  
  15.         b = ((a&b)<<1);   //进位  
  16.         a = ans;  
  17.     }  
  18.     return a;  
  19. }  
  20.   
  21. //这个和加法一样了,首先取减数的补码,然后相加。  
  22. int negtive(int a)   //取补码  
  23. {  
  24.     return Add(~a, 1);  
  25. }  
  26. int Sub(int a, int b)  
  27. {  
  28.     return Add(a, negtive(b));  
  29. }  
  30.   
  31. // 判断正负   
  32. int ispos( int a )   
  33. //正  
  34.     return (a&0xFFFF) && !(a&0x8000);  
  35. }  
  36. int isneg( int a )   
  37. //负  
  38.     return a&0x8000;  
  39. }  
  40. int iszero( int a )  
  41. //0  
  42.     return !(a&0xFFFF);  
  43. }  
  44.   
  45. //正数乘法运算  
  46. int Pos_Multiply(int a,int b)  
  47. {  
  48.     int ans = 0;  
  49.     while(b)  
  50.     {  
  51.         if(b&1)  
  52.             ans = Add(ans, a);  
  53.         a = (a<<1);  
  54.         b = (b>>1);  
  55.     }  
  56.     return ans;  
  57. }  
  58.   
  59. //乘法运算  
  60. int Multiply(int a,int b)  
  61. {  
  62.     if( iszero(a) || iszero(b) )  
  63.         return 0;  
  64.     if( ispos(a) && ispos(b) )  
  65.         return Pos_Multiply(a, b);  
  66.     if( isneg(a) )  
  67.     {  
  68.         if( isneg(b) )  
  69.         {  
  70.             return Pos_Multiply( negtive(a), negtive(b) );  
  71.         }  
  72.         return negtive( Pos_Multiply( negtive(a), b ) );  
  73.     }  
  74.     return negtive( Pos_Multiply(a, negtive(b)) );  
  75. }  
  76.   
  77. //除法就是由乘法的过程逆推,依次减掉(如果x够减的)y^(2^31),y^(2^30),...y^8,y^4,y^2,y^1。减掉相应数量的y就在结果加上相应的数量。  
  78. int Pos_Div(int x,int y)  
  79. {  
  80.     int ans=0;  
  81.     for(int i=31;i>=0;i--)  
  82.     {  
  83.         //比较x是否大于y的(1<<i)次方,避免将x与(y<<i)比较,因为不确定y的(1<<i)次方是否溢出  
  84.         if((x>>i)>=y)  
  85.         {  
  86.             ans+=(1<<i);  
  87.             x-=(y<<i);  
  88.         }  
  89.     }  
  90.     return ans;  
  91. }  
  92.   
  93. //除法运算  
  94. int MyDiv( int a, int b )  
  95. {  
  96.     if( iszero(b) )  
  97.     {  
  98.         cout << "Error" << endl;  
  99.         exit(1);  
  100.     }  
  101.     if( iszero(a) )  
  102.         return 0;  
  103.     if( ispos(a) )  
  104.     {  
  105.         if( ispos(b) )  
  106.             return Pos_Div(a, b);  
  107.         return negtive( Pos_Div( a, negtive(b)) );  
  108.     }  
  109.     if( ispos(b) )  
  110.         return negtive( Pos_Div( negtive(a), b ) );  
  111.     return Pos_Div( negtive(a), negtive(b) );  
  112. }   
  113.   
  114.   
  115. // 比较两个正数的大小(非负也可)   
  116. int isbig_pos( int a, int b )   
  117. {  //a>b>0  
  118.     int c = 1;  
  119.     b = (a^b);  
  120.     if( iszero(b) )  
  121.         return 0;  
  122.     while( b >>= 1 )  
  123.     {  
  124.         c <<= 1;  
  125.     }  
  126.     return (c&a);  
  127. }   
  128.   
  129. // 比较两个数的大小   
  130. int isbig( int a, int b )   
  131. //a>b  
  132.     if( isneg(a) )  
  133.     {  
  134.         if( isneg(b) )  
  135.         {  
  136.             return isbig_pos( negtive(b), negtive(a) );  
  137.         }  
  138.         return 0;  
  139.     }  
  140.     if( isneg(b) )  
  141.         return 1;  
  142.     return isbig_pos(a, b);  
  143. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值