1. 程式人生 > 其它 >位運算實現算術運算

位運算實現算術運算

技術標籤:Leetcode

實現加法

數在計算機中為補碼錶示,具體體現為正數為原碼,負數為原碼取反+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);
}

易錯點,討論正負的情況