最近,在百度知道上回答问题,然后看见有的人问如何用位移运算符去进行加减乘除运算,于是巩固今天就在这总结一下。

  先讲讲总体思路:
加法运算:将一个整数用二进制表示,其加法运算就是:相异(^)时,本位为1,进位为0;同为1时本位为0,进位为1;同为0时,本位进位均为0.所以,不计进位的和为sum
= a^b,进位就是arr =
a&b,(与sum相加时先左移一位,因为这是进位)。完成加法直到进位为0.

减法运算:a-b  =
a+(-b)  根据补码的特性,各位取反加1即可(注意得到的是相反数,不是该数的补码,因为符号位改变了)

(上面用二进制实现的加减法可以直接应用于负数)

乘法运算:原理上还是通过加法计算。将b个a相加,注意下面实际的代码。

除法运算:除法运算是乘法的逆。看a最多能减去多少个b。

1、加法:
int AddWithoutArithmetic(int num1,int
num2)  
{  
   
if(num2==0) return num1;//没有进位的时候完成运算
 
   
int sum,carry;  
   
sum=num1^num2;//完成第一步没有进位的加法运算  
   
carry=(num1&num2)<<1;//完成第二步进位并且左移运算
 
   
return AddWithoutArithmetic(sum,carry);//进行递归,相加
 
}
 
其实这个还可以写得更简单,我们用的思路就是先不计进位相加,然后再与进位相加,随着递归,进位会变为0,递归结束。代码如下:
int Add(int a,int b)
 
{  
   
return b ? Add(a^b,(a&b)<<1) : a;
 
   
 
}  

  当然递归有时候不好理解,所以我有写个不用递归的:
int Add(int a, int b)
 
{  
   
int ans;  
   
while(b)  
    {
  //直到没有进位  
   
    ans = a^b;  
     //不带进位加法
 
   
    b = ((a&b)<<1);
  //进位  
   
    a = ans;
 
    }
 
   
return a;  
}  

2、减法:
//这个和加法一样了,首先取减数的补码,然后相加。
 
int negtive(int a)  
//取补码  
{  
   
return Add(~a, 1);  
}  
int Sub(int a, int b)
 
{  
   
return Add(a, negtive(b));  

3、正数乘法运算:
//正数乘法运算  
int Pos_Multiply(int a,int b)
 
{  
   
int ans = 0;  
   
while(b)  
    {
 
   
    if(b&1)
 
   
     
  ans = Add(ans, a);
 
   
    a = (a<<1);
 
   
    b = (b>>1);
 
    }
 
   
return ans;  
}  
 

4、正整数除法:
//除法就是由乘法的过程逆推,依次减掉(如果x够减的)y^(2^31),y^(2^30),...y^8,y^4,y^2,y^1。减掉相应数量的y就在结果加上相应的数量。
 
int Pos_Div(int x,int y)
 
{  
   
int ans=0;  
   
for(int i=31;i>=0;i--)  
    {
 
   
   
//比较x是否大于y的(1<<i)次方,避免将x与(y<<i)比较,因为不确定y的(1<<i)次方是否溢出
 
   
    if((x>>i)>=y)
 
   
    {
 
   
     
  ans+=(1<<i);
 
   
     
  x-=(y<<i);  
   
    }
 
    }
 
   
return ans;  
}  

最后汇总一下:
// 加减乘除位运算
  
// 程序中实现了比较大小、加减乘除运算。所有运算都用位操作实现
  
// 在实现除法运算时,用了从高位到低位的减法
  
// 具体如下,算法也比较简单,所以没有作注释
 
#include  
#include  
using namespace std;
 
  
int Add(int a, int b)
 
{  
   
int ans;  
   
while(b)  
    {
 //直到没有进位  
   
    ans = a^b;  
     //不带进位加法
 
   
    b = ((a&b)<<1);
  //进位  
   
    a = ans;
 
    }
 
   
return a;  
}  
  
//这个和加法一样了,首先取减数的补码,然后相加。
 
int negtive(int a)  
//取补码  
{  
   
return Add(~a, 1);  
}  
int Sub(int a, int b)
 
{  
   
return Add(a, negtive(b));  
}  
  
// 判断正负
  
int ispos( int a )
  
{ //正  
   
return (a&0xFFFF) && !(a&0x8000);
 
}  
int isneg( int a )
  
{ //负  
   
return a&0x8000;  
}  
int iszero( int a )
 
{ //0  
   
return !(a&0xFFFF);  
}  
  
//正数乘法运算  
int Pos_Multiply(int a,int b)
 
{  
   
int ans = 0;  
   
while(b)  
    {
 
   
    if(b&1)
 
   
     
  ans = Add(ans, a);
 
   
    a = (a<<1);
 
   
    b = (b>>1);
 
    }
 
   
return ans;  
}  
  
//乘法运算  
int Multiply(int a,int b)
 
{  
   
if( iszero(a) || iszero(b) )  
   
    return 0;
 
   
if( ispos(a) && ispos(b) )  
   
    return Pos_Multiply(a, b);
 
   
if( isneg(a) )  
    {
 
   
    if( isneg(b) )
 
   
    {
 
   
     
  return Pos_Multiply( negtive(a), negtive(b) );
 
   
    }
 
   
    return negtive( Pos_Multiply(
negtive(a), b ) );  
    }
 
   
return negtive( Pos_Multiply(a, negtive(b)) );
 
}  
  
//除法就是由乘法的过程逆推,依次减掉(如果x够减的)y^(2^31),y^(2^30),...y^8,y^4,y^2,y^1。减掉相应数量的y就在结果加上相应的数量。
 
int Pos_Div(int x,int y)
 
{  
   
int ans=0;  
   
for(int i=31;i>=0;i--)  
    {
 
   
   
//比较x是否大于y的(1<<i)次方,避免将x与(y<<i)比较,因为不确定y的(1<<i)次方是否溢出
 
   
    if((x>>i)>=y)
 
   
    {
 
   
     
  ans+=(1<<i);
 
   
     
  x-=(y<<i);  
   
    }
 
    }
 
   
return ans;  
}  
  
//除法运算  
int MyDiv( int a, int b )
 
{  
   
if( iszero(b) )  
    {
 
   
    cout << "Error"
<< endl;  
   
    exit(1);
 
    }
 
   
if( iszero(a) )  
   
    return 0;
 
   
if( ispos(a) )  
    {
 
   
    if( ispos(b) )
 
   
     
  return Pos_Div(a, b);
 
   
    return negtive( Pos_Div( a,
negtive(b)) );  
    }
 
   
if( ispos(b) )  
   
    return negtive( Pos_Div(
negtive(a), b ) );  
   
return Pos_Div( negtive(a), negtive(b) );
 
}
  
  
  
// 比较两个正数的大小(非负也可)
  
int isbig_pos( int a, int b )
  
{  //a>b>0
 
   
int c = 1;  
    b
= (a^b);  
   
if( iszero(b) )  
   
    return 0;
 
   
while( b >>= 1 )  
    {
 
   
    c <<= 1;
 
    }
 
   
return (c&a);  
}
  
  
// 比较两个数的大小
  
int isbig( int a, int b )
  
{ //a>b
 
   
if( isneg(a) )  
    {
 
   
    if( isneg(b) )
 
   
    {
 
   
     
  return isbig_pos( negtive(b), negtive(a) );
 
   
    }
 
   
    return 0;
 
    }
 
   
if( isneg(b) )  
   
    return 1;
 
   
return isbig_pos(a, b);  
}  

最新文章

  1. 调用手机在线API获取手机号码归属地信息
  2. 6. web前端开发分享-css,js移动篇
  3. Java NIO2:缓冲区
  4. ASP.NET 教程(一)
  5. js 九九乘法表
  6. VLAN 间路由的几种方法
  7. Shell 操作练习
  8. jsp常用JSTL
  9. hadoop-2.7.1基于QMJ高可用安装配置
  10. Eclipse启动的时候窗口一闪就关的解决办法(转)
  11. Eclipse自动补全功能轻松设置 || 不需要修改编辑任何文件
  12. Leetcode 283 Move Zeroes python
  13. 安装64位的oracle连接客户端
  14. transform 属性小解
  15. ES6对象及ES6对象简单拓展
  16. IDEA的Maven依赖如何引入到External Libraries中
  17. Docker的名字空间
  18. linux服务基础(三)之Httpd2.4配置
  19. HDU 4825 Xor Sum (模板题)【01字典树】
  20. if条件简单语法

热门文章

  1. openstack(Pike 版)集群部署(四)--- Nova 部署
  2. WAS 常见报错
  3. 最小生成树算法(krustra+prime)
  4. linux同步机制2
  5. vue 添加子路由,并对路由重定向
  6. css浮动知识点(转)
  7. 路径打印(set以及字符串的相关操作)
  8. MVC 学习(一)Linq to Entities 简单Demo
  9. Quartz代码及配置详解(转)
  10. docker-ce-17.09 仓库的创建与使用