和乘法一样,我们可以通过不断的减法来实现除法,但是,同样的,我们可以借助数学技巧来获得更好的实现。
首先我们来看一下以下两个数的除法:
1
-----------------------------
1 0 1 0 | 1 0 1 0 0 0 1 1
| 1 0 1 0
当我们像这样进行除法计算的时候,我们的下一步应该是:
1
-----------------------------
1 0 1 0 | 1 0 1 0 0 0 1 1
| 1 0 1 0
---------------------------
0 0 0 0
此时,我们进行了一次减法,我们减去的是什么数字呢?是 1010 吗?很明显,不是的,而是:
1
-----------------------------
1 0 1 0 | 1 0 1 0 0 0 1 1
| 1 0 1 0 0 0 0 0
---------------------------
0 0 0 0 0 0 1 1
这相当与将 1010 向左移了 4 位,我们在更换数字尝试一下:
1
-----------------------------
1 0 1 1 | 1 0 1 0 1 0 1 1
| 1 0 1 1 0 0 0
---------------------------
1 0 1 0 0 1 1
很明显,这相当于将数字 1011 向左移了 3 位,为什么不移 4 位呢?因为如果移 4 位,得到的除数就比被除数大了。
由此,我们可以归纳出除法需要进行的步骤:
首先将除数和被除数进行对齐,即除数和被除数的第一个 1 在同一位上
判断除数是否大于等于被除数,如果为否,就不断右移除数,直到为真
用除数减去当前的被除数,减法的结果作为新的被除数
重复前面的步骤,直到被除数为 0
然后,我们就可以尝试实现了:
//计算整数 a 的有效位长度
int bitlength(int a) {
int length = 0;
while (a) {
plus(length, 1);
a = a >> 1;
}
return length;
}
//计算整数 a 和 b 的有效位长度的差值
int lengthdiff(int a, int b) {
return subtract(bitlength(a), bitlength(b));
}
int division(int a, int b) {
int dividend = abs(a), divisor = abs(b);
int quotient = 0;
for (int i = lengthdiff(dividend, divisor); i >= 0; i = subtract(i, 1)) {
int r = (divisor << i);
//Left shift divisor until it's smaller than dividend
if (r <= dividend) {
quotient |= (1 << i);
dividend = subtract(dividend, r);
}
}
if ((a ^ b) < 0) {
quotient = negate(quotient);
}
return quotient;
}