题目
Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
题意
对两个整数做除法,不能使用乘法、除法、模运算。如果溢出,返回MAX_INT.
分析
博主看到这道题,第一反应是设一个中间值temp,当被除数小于temp的时候,temp+除数,加除数的次数则是所求的结果。
看discussion votes最多的一个帖子,发现使用位运算的方法要高效很多。即,当temp小于被除数的时候,把temp做位运算,左移一位(加倍),result也左移一位(加倍),循环这个操作。
如下:
被除数:1024 temp:2
被除数:1024 temp:4
被除数:1024 temp:8
被除数:1024 temp:16
被除数:1024 temp:32
被除数:1024 temp:64
被除数:1024 temp:128
被除数:1024 temp:256
被除数:1024 temp:512
被除数:1024 temp:1024
被除数:1024 temp:2048被除数: 1024 除数:1 result: 1024
然后还需要注意的是,这个函数做的是int的除法,需要考虑负数
、溢出
的问题。
计算机是用补数表示负数的,int是32位,其能表示的数的范围为:
正负数 | 二进制 | 数值 |
---|---|---|
正数 | 0 ~ 2^31 | 0 ~ 2147483647 |
负数 | 2^31+1 ~ 2^32-1 | -2147483648 ~ -1 |
注意int类型的 -2147483648 是没办法取绝对数的,必须另外定义一个 long 类型的变量来进行转换。
**注意事项**
1. 溢出。除数为0,比如1/0;或者-2147483648(INT_MIN)/-1(因为int能表示的最大正整数比2147483648小 1 )。
2. 负数除法
代码
int divide(int dividend, int divisor) {
if(divisor==0 || (dividend==INT_MIN && divisor ==-1))
return INT_MAX;
int result = 0, tag = (dividend>0)^(divisor>0) ? 0:1;
long temp, div, dvd = labs(dividend), dis = labs(divisor);
while(dvd>=dis){
temp = 1;
div = dis;
while(dvd>=div){
div <<= 1;
temp <<= 1;
}
dvd -= (div>>1);
result+= (temp>>1);
}
return tag ? result : -result;
}
耗时42ms