*LeetCode--29. Divide Two Integers(两数相除,用位运算实现四则运算)
相关资料:用位运算实现四则运算:http://blog.csdn.net/hackbuteer1/article/details/7390093
题目大意:给出两个除,求二者的商,注意不能用乘法、除法、求余
方法1:
思路:用被除数减除数,看能减多少次。
不足:效率低,当特别大的数除以1时,计算很慢,提交超时。 代码如下:
public static int divide(int dividend, int divisor) { if(divisor == 0) return Integer.MAX_VALUE; if(dividend == 0) return 0; boolean flag = true; //指示正负号 if(dividend <0 && divisor>0||dividend>0&&divisor<0) flag = false;//负号 dividend = Math.abs(dividend); divisor = Math.abs(divisor); int solu = 0; while(dividend>=divisor){ solu++; dividend-=divisor; } if(flag == false) return -solu; else return solu; }
方法2:
思路:使用位运算。
除法就是由乘法的过程逆推,被除数x依次减掉(如果x够减的)y*(2^31),y*(2^30),...y*8,y*4,y*2,y*1。减掉相应数量的y就在结果加上相应的数量。
核心代码:
long ans = 0; for (int i = 31; i >= 0; i--) { // 比较dived是否大于divsor的(1<<i)次方,避免将dived与(divsor<<i)比较,因为不确定divsor的(1<<i)次方是否溢出 if ((dived >> i) >= divsor) { ans += (1 << i); dived -= (divsor << i); } }
另外需要注意的问题有:除数为0,还有计算的时候因为使用的是绝对值,因此需要考虑最大正数和最大负数的问题。
完整代码:
//除法就是由乘法的过程逆推, //依次减掉(如果x够减的)y*(2^31),y*(2^30),...y*8,y*4,y*2,y*1。 //减掉相应数量的y就在结果加上相应的数量。 public static int divide(int dividend, int divisor) { if (divisor == 0) return Integer.MAX_VALUE; if (dividend == 0) return 0; long dived = dividend; long divsor = divisor; System.out.println(dived+" "+divsor); boolean flag = true; // 指示正负号 if (dived < 0 && divsor > 0 || dived > 0 && divsor < 0) flag = false; // 负号 dived = Math.abs(dived); divsor = Math.abs(divsor); System.out.println(dived+" "+divsor); long ans = 0; for (int i = 31; i >= 0; i--) { // 比较dived是否大于divsor的(1<<i)次方,避免将dived与(divsor<<i)比较,因为不确定divsor的(1<<i)次方是否溢出 if ((dived >> i) >= divsor) { ans += (1 << i); dived -= (divsor << i); } } if(Math.abs(ans)>Integer.MAX_VALUE&&flag==true) //结果超过最大正数,返回最大正数 return Integer.MAX_VALUE; if (flag == false) return (int) -ans; else return (int) ans; }
注意,上面的31只是最大的次数也就是被除数最大可以减去divsor*2^31,(根据int范围是2^31-1到-2^31),还可以将for循环改成如下代码:
//下面的31代表最大值,还可以将代码改成这样 int digit = 0;while(divisor<=(dividend>>1)){ divisor <<= 1; digit++; } while(digit>=0) { if(dividend>=divisor) { dividend -= divisor; res += 1<<digit; } divisor >>= 1; digit--; }
补充:用位运算实现乘法运算
//正数乘法运算 public static int Pos_Multiply(int a,int b) { int ans = 0; while(b!=0) { if((b&1)==1) ans = ans+a; a = (a<<1); b = (b>>1); } return ans; }
例如 a*100
100转换为二进制为:110010
因此:a*100= a*2^6 + a*2^5 + a*2^2

浙公网安备 33010602011771号