实现加法
数在计算机中为补码表示,具体体现为正数为原码,负数为原码取反+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);
}
易错点,讨论正负的情况