Divide_Two_Integers(低时间复杂度版)

题目描述:Divide two integers without using multiplication, division and mod operator.

                译:(除两个数不使用乘除取余)

                代码是网上看见的,注释是自己加的,这个写的挺有意思的,但可能有点难懂。

public class Divide_Two_Integers2 {
	public static int divide(int dividend, int divisor) {
	    //除数为0则返回无穷大
	    if(divisor == 0)  
	    {  
	        return Integer.MAX_VALUE;  
	    }  
	    //这里是判断两个整数是不是同号的简便写法,也可以写成乘法, 但是那样又有越界的可能, 而且乘法的计算复杂度比位运算要高。
	    //这里是异或,同0异1,int类型32位,向右移31位剩下的就只是符号位,>>表示右移,如果该数为正,则高位补0,若为负数,则高位补1;
            //>>>表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0。
	    boolean isNeg = (dividend^divisor)>>>31 == 1;
	    //记录结果
	    int res = 0;  
	    if(dividend == Integer.MIN_VALUE)  
	    {  
	    	//之所以这么做是为了避免下面对dividend求abs时发生溢出,Math.abs(-2147483648) = -2147483648,要避免这种情况
	        dividend += Math.abs(divisor); 
	        //int的取值范围[-2147483648, 2147483647],即最小值的abs比最大值的abs大1,
	        //那么,除法却发生溢出的情况仅仅当:dividend=-2147483648,divisor=-1
	        if(divisor == -1)  
	        {  
	            return Integer.MAX_VALUE;  
	        }  
	        //此处result要记得加1,因为被除数里已经加了一个除数
	        res++;  
	    }  
	    //当divisor为MIN时,结果要么为1(dividend也为MIN),要么为0
	    if(divisor == Integer.MIN_VALUE)  
	    {  
	        return res;  
	    }
	    //取绝对值
	    dividend = Math.abs(dividend);  
	    divisor = Math.abs(divisor);
	    //记录除数一共向左移了几位
	    int digit = 0; 
	    //让除数左移直到大于被除数之前得到一个最大的基,左移相当于一个数乘2,右移相当于除2
	    //这里小于等于被除数的一半原因就是除数再向左移一位就等于乘了2,所以小于等于被除数的一半就是小于被除数之前最大的基
	    //如果在这个数基础上再乘2,那么就会比被除数大
	    while(divisor <= (dividend>>1))  
	    {  
	        divisor <<= 1;  
	        digit++;  
	    }
	    
	    //先用被除数减去刚刚由除数得到的那个最大的基,然后使基不断减小(实质上就是2^digit*divisor,减小的是digit)
            //如果剩余的数可以减去这个缩小的基则再减
	    //同时结果加上2^digit,重复过程直到digit小于零为止,实质上就是求已知除数之外的另一个除数的二进制表达式,digit就是幂,再转化为十进制。
	    //如87/4得到digit=4,按上述方法求得到result=1*2^4+0*2^3+1*2^2+1*2^0=21,至于系数是0或1则是if里的代码控制
	    while(digit>=0)  
	    {  
	        if(dividend>=divisor)  
	        {  
	            res += 1<<digit;  
	            dividend -= divisor;
	           
	        }
	        
	        divisor >>= 1;  
	        digit--;  
	    }  
	    //判断正负返回结果
	    return isNeg?-res:res;  
	}
	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		int num1=sc.nextInt();
		int num2=sc.nextInt();
		System.out.println(divide(num1,num2));
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值