位運算實現算術運算
阿新 • • 發佈:2021-01-16
技術標籤: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);
}
易錯點,討論正負的情況