Dividing Binary Numbers - Part 1- 6 mins
As I’ve been building a decimal number implementation in Rust I’ve needed to think about some numerical algorithms from a binary level - some which can initially seem non trivial. One situation falling into this category is division. Before going into the specifics of the Rust implementation I thought I’d cover the different ways to perform division using binary numbers. Consequently I’ve broken this topic into many parts:
- Part 1 - Division using Long Division
- Part 2 - Division using Two’s Complement
- Part 3 - A simple implementation of division in Rust
- Part 4 - A decimal implementation in Rust
- Part 5 - Optimizing the decimal implementation in Rust
Now to get stuck into it!
A refresher on long division in base10
If you’re like me, it’s been a long time since you’ve had to perform long division. In fact, I’d personally “moved” that knowledge aside in lieu of short division techniques. Accordingly, it’s worthwhile refreshing our long division knowledge. We’ll practice long division on . Before diving into this, let’s cover some terminology:
- Dividend - the number that is being divided. In our example: .
- Divisor - the number that another number, the dividend, is to be divided. In our example: .
- Quotient - the number obtained by dividing one quantity by another. In our example: .
Or to simplify:
Ok, now we’ve got the definitions out of the way let’s cover the generic steps we need to follow:
- Compare the divisor to the first digit of the dividend. If the divisor is bigger than the first digit then keep “adding numbers” until the divisor is less than or equal to the number.
- Divide the subsequent number and use the result as the first digit of the quotient.
- Multiply the quotient digit with the divisor and write the result underneath the number.
- Subtract the multiplied result from the dividend’s digits to find the remainder.
With anything, an example is easier. Using our earlier example we start by writing the equation as:
Comparing the divisor with the first digit we find that . Consequently, we keep “adding” numbers until the divisor is less than the comparison. In this case, if we take the next digit we can see that . Success!
Moving onto step two, we now divide by and use the result as the first number of the quotient. Of course, goes into four times with a remainder of one. Consequently, we write this into our equation:
We then continue and multiple the digit with the divisor (i.e. ) and write the result underneath:
Moving to step four we subtract the multiplied result from the dividend’s digits to find the remainder. We also carry down the next digit, in this case :
We now do the same operations on the new remainder. In this case we will do and put the result in the next position:
To round off, we multiply the new digit () with the divisor and subtract from the existing remainder:
We’ve got no remainder so we’re done - and we have our result of . If we had to keep going we’d need to introduce a decimal point since we’re shifting past the integral section. This isn’t relevant at present so we’ll skip that part and move onto binary.
Long division in binary
Long division in binary is actually very similar, albeit much simpler! For the binary division example we’ll use something which fits into a byte for simplicity: or better represented as .
Firstly, let’s set up the problem the same way (leading zeroes omitted):
Now we compare the divisor with the first digit as we did in base10. In this case can’t go into so we put a in the first place and keep searching. In this example, we keep searching until we get to in which can be divided into exactly once. This is actually fairly typical in binary long division - it either goes into the number or doesn’t:
The next step of multiplication is relatively trivial since we’re working with zeroes or ones! So we put the divisor underneath, subtract to get the remainder and carry down the next digit:
Now, doesn’t go into so we put a within the next position of the quotient and carry down the next number:
does go into so we add a one to the quotient and work out the remainder (plus carry down the next digit):
We carry on repeating this pattern: doesn’t go into so we put a zero in the quotient and carry down the next number:
goes into exactly once so we place a in the final position and round off the remainder:
If we change our binary number to decimal, as expected, we get .
What about fractional numbers?
What if we didn’t have a clean division at the end? For the purposes of simplicity, for now we’ll just treat the remainder as exactly that, the remainder:
In this example, we have which will result in with a remainder of . We’ll dig into how to represent fractional numbers in computer memory in a future post.
Hopefully you found this post useful. I’ll be following up with the two’s complement method of division in a couple of weeks.