部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

*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

 

posted @ 2015-07-17 16:01  流了个火  阅读(152)  评论(0)    收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats