Reputation: 909
I am going through the "Elements of Programming Interview" in python currently and have gotten stuck at this part. The code below is simply multiplies two numbers without using any operators; the explanation given by the authors is below:
We can compute the largest k such that (2^k)y <= x, subtract (2^k)y from x, and add 2^k to the quotient. For example is x = (1011) and y =(10), then k = 2, since 2 x 2^2 <= 11 and 2 x 2^3 > 11. We subtract (1000) form (1011) to get (11), add 2^k = 2^2 = (100) to the quotient, and continue by updating x to (11).
A better way to find the largest k in each iteration is to recognize that it keeps decreasing. Therefore, instead of testing in each iteration whether (2^0)y, (2^1)y, (2^2)y, ... is less than or equal to x, after we initially find the largest k such that (2^k)y <= x, in subsequent iteration we test (2^k-1)y, (2^k-2)y, (2^k-3)y, ... with x. For the example given earlier, after setting the quoient to (100) we continue with (11). Now the laegest k such that (2^k)y <= (11) is 0, so we add 2^0 = (1) to the quotient, which is now (101). We continue with (11) - (10) = (1), Since (1)
def divide(x, y):
result, power = 0, 32
y_power = y << power
while x >= y:
while y_power > x:
y_power >>= 1
power -= 1
result += 1 << power
x -= y_power
return result
My Questions are:
Upvotes: 2
Views: 457
Reputation: 889
This is long division for binary numbers. You probably learned this for decimal numbers in school.
If we want to divide x
by y
we ask our self "how many times does y
fit into x
if we add as many zeros to it as possible?". Adding n zeros to y
is equivalent to multiplying with 2^n or shifting left by n.
power = 32
y_power = y << power
The first guess of the algorithm is to add 32 zeros to y
, which is shifting it left with power
. So, if you know your result might be >= 2^33, you would have to use a larger initial value for power
.
while y_power > x:
y_power >>= 1
power -= 1
In the inner loop it will test if y_power
already fits into x
and if not, will "move it one digit to the right".
result += 1 << power
When this is done, it will just write the "number of how many times y shifted left fits into x" to the result. As in binary numbers this can just be zero or one and the inner loop skipped all zeros, this must be one.
x -= y_power
As you know from long division, we now need to subtract this multiple of the divisor, y
, from the dividend and continue with the result.
while x >= y:
We will stop if this difference, y
, is smaller than x
and it is therefore impossible for 2^power * y
to fit into x
.
Example Let's calculate 15/5:
1111 / 101 = 11
-1010
------
101
-101
------
0
We have x
=1111 and y
=101 and start with with power=1
for brevity. First we calculate y_power = y<<power = 101<<1 = 1010
. As 1010 > 1111
is false we skip the inner loop and add 1<<power = 1<<1 = 10
to the result. Then we subtract y_power = 1010
from x = 1111
and get 101
. Now y_power = 1010 > 101 = x
is true and we decrement power
, so we get power = 0
and y_power = y<<power = 101
. Now y_power>x
is false again and we add 1<<power = 1
to our result and get x - y_power = 0
. Now x >= y
is false and we are finished with result = 11
.
Upvotes: 3