问题描述:给定两个整数,被除数dividend和chushudivisor。将两数相除,要求不使用乘法、除法、mod运算。返回被除数dividend除以除数divisor得到的商。
解法一:这题说了不能使用*,/,%等符号,那么只能使用减法了,一种方式就是不停地减,比如20/3,用20不停地减去3,但这种效率太差。可以用20减去3的倍数,减去6要比减去3更快,当不够减的时候在减去3.,所以发现一个规律,就是把除数不停地往左移,只要比被除数小即可,减去除数,更新个数,转化为正数求解,为了防止溢出,使用long来装,
public int divicd(int dividend,int divisor)
{
int sign=(dividend^divisor)>0?1:-1;
long Ldividend=Math.abs((long)dividend);
long Ldivisor=Math.abs((long)divisor);
int resTime=0;
while(Ldividend>Ldivisor)
{
long tempdivisor=Ldivisor;
int times=1;
while(Ldividend>tempdivisor)
{
Ldividend-=tempdivisor;
tempdivisor<<1;
times<<1;
}
Ldivisor=tempdivisor>>1;
resTime+=times>>1;
}
return resTime*sign;
}
解法二:上面的解法具有一定的局限性,为了防止溢出我们可以把int转化为long类型,但如果题目中哥给出的是long类型,那么就没有办法了。实际上也可以不用转,我们来看一下int类型的范围:
-2147483648到2147483647,也就会说把一个复数转为整数可能会溢出,但将一个正数转为复数的过程中不会出现溢出;
public int mod(int left,int right)
{
int sign=(left^right)>0?1:-1;
int dividend=-Math.abs(left);
int divisor=-Math.abs(right);
int times=0;
int res=0;
while(dividend<divisor)
{
times=1;
tempdivisor=divisor;
while(dividend<temodivisor)
{
dividend-=temodivisor;
times<<1;
divisor<<1;
}
res+=times>>1;
}
return res*sign;
}
难度升级:这题说了不能使用乘法,出发,求余运算符,如果限制以下,除了上述3种运算符以外,还不能使用+,-符号,看下该怎么解;
public int sub(int a,int b)
{
if(b==0){return a;}
int c=a&b;
a=a^c;
b=b^c;
return sub(a|b,b<<1);
}
public int Mod(int left,int right)
{
int sign=(left^right)>0?1:-1;
int dividend=sign==1?~sub(left,1):left;
int divisor=sign==1?~sub(right,1):right;
int res=0;
while(dividend<divisor)
{
int time=1;
int tempdivisor=divisor;
while(dividend<tempdivisor)
{
dividend=sub(dividend,divisor);
time<<1;
tempdivisor<<1;
}
res++time>>1;
}
return res*sign;
}