位运算实现算术运算

实现加法

数在计算机中为补码表示,具体体现为正数为原码,负数为原码取反+1

对于num1 num2 其
各位值按位或求得加法后的值 即 1|1=0 1|0=1 0|1=1 0|0=0
进位值按位与求得加法后的进位,之后再左移一位
最后结束循环的过程为不再拥有进位

int add(int num1,int num2)
{
    while(num1!=0) //存在进位
    {
        int temp=num2;
        num2=num2^num1;//作异或运算
        num1=(num1&temp)<<1;//进位
    }
    return num2; 
}

实现减法

减法的本质为加上一个相反数
而相反数,可以理解为取反+1 即补码的过程
如2的二进制 000…00010 =》111… 1101+1=》11…1110 注意前面还有符号位刚好为-2

int sub(int num1,int num2)
{
   num2=add(~num2,1);//取得相反数
    return add(num1,num2); 
}

实现乘法

乘法的本质为加法,因此朴素的解法是不断累加
进阶做法:移位+累加

如num1*num2 而num2在二进制中表现为若干个二进制位为1
若第i位为1 则 ans=add(ans,num1<<i)
那么从num2的最后一个二进制位开始扫描,直到统计完各位情况

int mutli(int num1,int num2)
{
    int ans=0;
    int mask=1;  //研究乘数num2各个位上的情况
    //如果最后一位为1 =》+num1
    //如果倒数二位为1 =》+num1的2次方
    //......以此类推  扫描一遍Num2即可
    while(mask!=0)
    {
        if((num2&mask)!=0)  //对应位存在数字
        {
            ans=add(ans,num1);
        }
        num1<<=1;
        mask<<=1;      
    }
    return ans;
}

实现除法

除法的过程和乘法是一个相反的过程
以num1/num2为例
若num1>>i 右移i位仍然比num2大,那么ans+=1<<i;
即num1>= 2的i次方个num2累积之和
若更大,那么减去那部分,剩下部分继续,i=31=>0 即先减去大部分,然后减去较小部分。

int divis(int num1,int num2)
{
    int ans=0;
    bool flag1=true;
    bool flag2=true;
    if(num1<0 )
    {
        num1=add(~num1,1);
        flag1=false;
    }
    if(num2<0)
    {
        num2=add(~num2,1);
        flag2=false;
    }

    //研究每一位的情况
    //因为num1一定是num2的2的若干次倍 累加起来
    for(int i=31;i>=0;i--)
    {
      
        if((num1>>i)>=num2)  //num1右移动i位仍然大于num2
        {
            ans+=(1<<i);
            num1=sub(num1, num2<<i);//减去这个倍数的值
        }
    }
    if((flag1==false && flag2==false)||(flag1==true && flag2==true))
        return ans;
    else
        return add(~ans,1);
}

易错点,讨论正负的情况

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:C马雯娟 返回首页