How to round binary numbers
We are all familiar with rounding numbers in decimal system. Rounding in binary system is similar, but it still may cause some confusion. The biggest challenge is rounding fractions. For example, it may not be obvious right away why the fraction 0.11101 when rounded to 2 places after the decimal point results in integer 1. This articles explains the general rules for binary fractions rounding and explains where they come from. The same rules apply to rounding binary integers.
There are five rounding methods, as defined by IEEE-754 standard, and most of them are pretty straightforward. The first two round to a nearest value (ties to even and ties away from zero); the others are called directed roundings: towards zero, towards positive infinity and towards negative infinity. These rules are easier to understand using decimal system as an example:
Directed roundings are pretty straightforward. In this article we’ll take a detailed look on the ‘round to the nearest; ties to even’ rule. It is the default mode for binary floating-point and the recommended default for decimal. And it’s usually not as easy to understand as directed roundings.
The general rule when rounding binary fractions to the n-th place prescribes to check the digit following the n-th place in the number. If it’s 0, then the number should always be rounded down. If, instead, the digit is 1 and any of the following digits are also 1, then the number should be rounded up. If, however, all of the following digits are 0’s, then a tie breaking rule must be applied and usually it’s the ‘ties to even’. This rule says that we should round to the number that has 0 at the n-th place.
To demonstrate those rules in action let’s round some numbers to 2 places after the radix point:
- 0.11001 — rounds down to 0.11, because the digit at the 3-rd place is 0
- 0.11101 —rounds up to 1.00, because the digit at the 3-rd place is 1 and there are following digits of 1 (5-th place)
- 0.11100 — apply the ‘ties to even’ tie breaker rule and round up because the digit at 3-rd place is 1 and the following digits are all 0's.
If you are like me, than where those rules come from might not be very clear at the first glance. It appears that no article I’ve read about rounding explains those rules in great detail using visual representation — but it’s exactly what I think is needed for clear explanation.
Rounding options
When we’re rounding numbers, we have to select one of the two possible options: either round down to a nearest number that is smaller than the original or round up to a nearest number which is bigger. These two numbers should have no more decimal places than the resulting number after the rounding.
To demonstrate how we identify those numbers let’s round decimal number 0.42385 to 2 places. What numbers can it be rounded to? This is easy to see if we put this number on the number line along with fraction numbers that have two places:
This diagram shows that our original number falls in between 0.42 and 0.43. As 0.42385 = 0.42 + 0.00385 and our lower number is 0.42, we may conclude that to find a lower number we can simply truncate the fractional part after the second place. And to find a higher number we can use already identified lower number and increase it by one ULP by adding 1 to the digit at the last place. Or, looking from a different angle, it means we should add to the lower number 0.01 — which is 1 multiplied by the 10 to the negative power of 2, because we’re rounding to 2 places. If we were rounding to 3 places, we would take a lower number for 3 places and add 1 multiplied by the 10 to the negative power of 3.
We can generalize this rule of finding rounding options:
When rounding a fraction number to n places, first find a lower number by discarding fractional part after the n-th place and then use it to find a higher number by adding to it one ULP — 1 multiplied by the numeric system base to the power of n.
Now, let’s find the rounding options for the binary number 0.11011. Again, we’ll be rounding to 2 places. If we follow the same pattern described for decimal fractions we get 0.11 for a smaller number, since 0.11011 = 0.11 + 0.00011. Then we can find a bigger number by adding 0.01, which is 1 multiplied by the 2 to the negative power of 2, because we’re are using binary system, hence the base is 2, and rounding to 2 places. The result of this calculation is 0.11+0.01=1.00.
Finding shortest distance
The ‘round to the nearest’ rounding rule says that we should round to the number which has the least difference with the original number. On the number line, this means the distance between the original and the two possible rounded numbers is the least. So if we put original number and possible options on the numbers line and mark distances as x’s, we need to find which x is smaller:
That’s quite easy to do by subtraction:
It’s clear here that x1 is smaller than x2 and we should round to 0.11 then. But what if we wanted to round infinite binary? In this case subtraction wouldn’t be such a straightforward operation. As it turns out, there’s much easier approach.
Comparing with the middle
Another easier approach is to identify whether the original number is bigger or smaller than the middle between two rounding options. Let’s see this diagram:
It should not be difficult to conclude that if a number is larger than the middle than it’s closer to the higher rounded number, otherwise it’s closer to the lower rounded number.
So how do we find that middle between two rounding options? Well, we know that the distance between 0.11 and 1.00 is 0.01. So we simply need to find the half of the 0.01 and add it to the lower number. The half is 0.001 and when added to the lower number it produces 0.111 = 0.11 + 0.001. Essentially, it’s equivalent to just appending 1 to the end of the lower number. Here is the diagram with relevant numbers put on the number line:
Now, the only thing that is left is to compare original number with the middle:
Using bit by bit lexicographical order comparison, it’s clear that 0.11011 is less than the middle. So we should round down to 0.11 and it’s the same result as we received by calculating distances.
Ties to even
Sometimes the distance between the original number and each rounding option is equal, so the rule ‘round to the nearest’ can’t be applied. Suppose we’re rounding the number 0.11011 to 4 places after the radix point. We know that we need to find two rounding options and the middle for comparison. So, to find first the smaller number we simply truncate the remaining digits after the 4-th place which gives us 0.1101. Now we can find the middle by appending 1 to the end of the lower number and we get 0.11011. And the last, let’s find the bigger number by adding 1 ULP to the smaller number — 0.1101+0.0001 = 0.1110.
So here we have:
- original number — 0.11011
- number to round down to — 0.1101
- number to round up to — 0.1110
- middle number between rounding options — 0.11011.
By going through bit by bit comparison, we can see that the original number and the middle are equal, which shows that the original number falls right in between two rounding options. This is exactly the situation where we need to apply the second part of the rule ‘ties to even’. Binary number is even if it ends with 0, so given our rounding options it’s the bigger number that is even and the rule instructs to round up to the 0.1110.
Inferring general rules for rounding
Do we really need to compare digits at all places? As you may have guessed from the rules outlined in the beginning of the article, we don’t need to. I’ve shown you in the previous paragraph that a middle number will always end with 1 at the n+1 place, where n is the number of places a number is rounded to. The original number and the middle will always be equal until the n+1 place — it means that this is the place we should start comparing numbers from onward.
So the general rules of rounding presented in the beginning of the article come from comparing the original number and the middle between two rounding options. I’ll repeat these rules here again:
The general rule when rounding to the n-th place prescribes to check the digit following the n-th place in the number. If it’s 0, then the number should always be rounded down. If, instead, the digit is 1 and any of the following digits is also 1, then the number should be rounded up. If, however, all of following digits are 0’s, then a tie breaking rule must be applied and usually it’s the ‘ties to even’. This rule says that we should round to the number that has 0 at the n-th place.