0.核心:倍增法
1.定义
不用乘除和取余运算符,只用加减移位来实现 dividend / divisor(整数除法)
‘除法在加减里面的负号只是负负得正的符号,不是衡量一个数的大小’
2.代码
public class A_Integer_division {
public int divide(int dividend, int divisor) {//接收两个整数参数:被除数 `dividend` 和 除数 `divisor`
if (dividend == 0x80000000 && divisor == -1) {//`0x80000000` 是 `Integer.MIN_VALUE`(-2147483648)
return Integer.MAX_VALUE;
}
int negative = 2;//统计结果是否为负数:如果 dividend 是正数,负数个数就少 1;如果 divisor 是正数,也少 1;最后根据 negative == 1 判断结果需要取负号
if (dividend > 0) {//如果 dividend 是正数:
negative--;//negative 减 1
dividend = -dividend;//转成负数:`-dividend`
}
if (divisor > 0) {//如果 divisor 是正数:
negative--;//negative 再减 1
divisor = -divisor;//转成负数
}
int result = divideCore(dividend, divisor);//调用私有方法 `divideCore`:用倍增法计算绝对值的除法结果
return negative == 1 ? -result : result;//如果 `negative == 1`,就返回 `-result`;
}//如果 negative == 1:说明只遇到一个负数,结果应该是负数;如果 negative == 0 或 2:结果是正数
private int divideCore(int dividend, int divisor) {//私有方法:divideCore;计算负数的绝对值除法
int result = 0;
while (dividend <= divisor) {//只要 dividend <= divisor,就说明还有数可以减
int value = divisor;//`value` 表示当前用来减的数(初始是 divisor)
int quotient = 1;//`quotient` 表示当前倍数(初始是 1)
while (value >= 0xc0000000 && dividend <= value + value) {//判断条件:1.`value >= 0xc0000000`:防止溢出(避免 value 翻倍后超过 int 范围;2.`dividend <= value + value`:确保 dividend 还够再减一次 value
quotient += quotient;//`quotient` 翻倍
value += value;//`value` 不断翻倍:`value += value` (相当于 *2)
}
result += quotient;//把当前的倍数加到结果里
dividend -= value;// 用 dividend 减掉当前的 value
}
return result;//返回最终结果(是正数)
}
public static void main(String[] args) {
A_Integer_division obj = new A_Integer_division();//创建当前类的对象
int ans = obj.divide(10, 3);//调用 `divide(10, 3)`,输出结果
System.out.println("10 / 3 = " + ans);
}
}
3.数字比喻
假设我们要算 10 ÷ 3
第一步:转成负数计算(为了防止溢出)原本:
dividend = 10
divisor = 3
我们统一转成负数:
dividend = -10
divisor = -3
负数更安全,因为 Integer.MIN_VALUE 无法转正数,而负数范围更大。
原因:
-
正数范围是 [-2^31 +1, 2^31 -1]
-
负数范围是 [-2^31, -1]
-
Integer.MIN_VALUE(-2^31)不能转成正数(溢出) -
所以全部转负数,更简单更安全
第二步:用倍增法去算「绝对值的除法结果」
想知道:10 ÷ 3 = ?
现在 dividend=-10, divisor=-3
过程:
1.看 -10 能不能减一次 -3:
-10 - (-3) = -7
quotient = 1
2.看 -7 能不能再减一次 -3:
-7 - (-3) = -4
quotient = 2
3.看 -4 能不能再减一次 -3:
-4 - (-3) = -1
quotient = 3
4.-1 已经不能再减 -3 了(-1 > -3,不满足条件)
最终结果:
- quotient=3,表示绝对值结果是 3
- 因为 dividend 和 divisor 同号(negative=2),结果是正数
转负数 → 倍增减法算绝对值 → 根据同号异号判断结果符号