整数除法
题目
思路
- 由于只不能用除号,因此可以用a不断减b,直到a小于b为止,计算减了多少次b。但这样如果遇到 2 ^ 31 / 1 的情况,就会比较慢,因此需要进行优化
-
可以在每次做减法之前,不断将除数乘2。直到被除数减去除数小于除数为止,这样就计算出了其中的一段商:假设除数乘了k次,这段商的值为2 ^ k
- 例如:计算15/2,将除数2不断乘2,当乘到8时,发现被除数15将去8等于7,小于8,就得到了其中的一段熵,由于乘了2次,这段商的值就为 2 ^ 2 = 4
- 将被除数减去除数,重复上面的过程,直到剩余的数小于除数为止
-
如果除数和被除数符号不同,先将两者转换为负数,再进行计算,最后再加上符号
- 为什么不都转换成正数?
- 因为当被除数为(-2 ^ 31)时,无法将其中正数来表示
-
如果结果溢出,返回整数最大值:
- 只有(-2 ^ 31)/(-1)会溢出,所以可以特殊判断
代码
public int divide(int a, int b) {
// 唯一可能溢出的情况
if (a == Integer.MIN_VALUE && b == -1) {
return Integer.MAX_VALUE;
}
// 都转化为负数操作
int negCount = 2;
if (a > 0) {
a = -a;
negCount--;
}
if (b > 0) {
b = -b;
negCount--;
}
int res = 0;
while (a <= b) {
int value = b;
int cur = 1;
// value >= Integer.MIN_VALUE / 2:防止溢出
// a <= value + value:当a比2倍的除数还大时,说明还可以将除数翻倍
while (value >= Integer.MIN_VALUE / 2 && a <= value + value) {
cur += cur;
// 除数每次翻倍
value += value;
}
a -= value;
res += cur;
}
// 只有当negCount为1时,需要补充符号
return negCount == 1 ? -res : res;
}