29. Divide Two Integers

 
    /*
     * 29. Divide Two Integers
     * 2016-4-17 by Mingyang
     * 这个我们就得使用位运算。我们知道任何一个整数可以表示成以2的幂为底的一组基的线性组合,
     * 即num=a_0*2^0+a_1*2^1+a_2*2^2+...+a_n*2^n。
     * 基于以上这个公式以及左移一位相当于乘以2,我们先让除数左移直到大于被除数之前得到一个最大的基。
     * 然后接下来我们每次尝试减去这个基,如果可以则结果增加加2^k,然后基继续右移迭代,直到基为0为止。
     * 因为这个方法的迭代次数是按2的幂直到超过结果,
     * 所以时间复杂度为O(logn)
     * int的绝对值,int里面有一个特殊的数字:-2147483648,它的绝对值或者相反数 2147483648是超出int的范围的,
     * 对于这一情况需要特殊处理。所以不能直接调用 divide(-dividend, divisor)或者divide(dividend, – divisor)。
     * 也不能写 int dv = abs(dividend)。处理方式是使用long long来保存其绝对值
     * 计算绝对值的时候要写 long long dv = abs((long long)dividens)的原因是,
     * abs()有两个重载版本,其中一个是abs(int),另外一个是abs(long),如果不进行显式转换,
     * 则调用abs(int),对-2147483648的返回结果仍是-2147483648
     * 计算两个整数商的时候,有两种选择:将被除数dv右移或者将除数ds右移,循环终止条件是dv < ds。
     * 以上代码选用了右移被除数dv。原因是:当dv最高位(除符号位外)为1时,
     * 左移ds可能因为小于dv而将ds的有效位从最左移出,既会使比较出错,也可能导致死循环。
     * 最后,在return res这里,还是可能会出错的,但是就不在这段程序的考虑范围了,错误输入: -2147483648, -
     */
    public int divide(int dividend, int divisor) {
        //handle special cases
        if(divisor==0) return Integer.MAX_VALUE;
        if(divisor==-1 && dividend == Integer.MIN_VALUE)
            return Integer.MAX_VALUE; 
        //get positive values
        long pDividend = Math.abs((long)dividend);
        long pDivisor = Math.abs((long)divisor); 
        int result = 0;
        while(pDividend>=pDivisor){
            //calculate number of left shifts
            int numShift = 0;    
            while(pDividend>=(pDivisor<<numShift)){
                numShift++;
            }     
            //dividend minus the largest shifted divisor
            result += 1<<(numShift-1);//这里用加,因为下面减去了曾经计算过的部分,所以用加
            //至于为什么要用1往左移?因为假设两个是倍数关系,96处于3的话,3左移5位到96,那么结果也是1左移5位
            pDividend -= (pDivisor<<(numShift-1));
        }     
        if((dividend>0 && divisor>0) || (dividend<0 && divisor<0)){
            return result;
        }else{
            return -result;
        }
    }
    /*
     *  这道题目也可以不用位运算
     *  见一下大神的算法
     *  每次减去那个数,然后减去以后除数乘以2,结果也乘以2.
     */
     public int divide1(int dividend, int divisor) {
            long  mul=1;long  count=0;
            Boolean neg=false;
            if(((dividend>0)&&(divisor<0))||((dividend<0)&&(divisor>0)))
             neg=true;
            long a=Math.abs((long)dividend),b=Math.abs((long)divisor);
            long ori=b;
            while(a>=ori)
            {
                 a=a-b;
                 count+=mul;
                 b=b<<1;
                 mul=mul<<1;
                if(a<b){
                    b=ori;
                    mul=1;
                }
            }
            if(neg)
             count*=-1;
            if(count>Integer.MAX_VALUE||count<Integer.MIN_VALUE)
             return Integer.MAX_VALUE;
            else
             return (int)count;
        }
原文地址:https://www.cnblogs.com/zmyvszk/p/5403071.html