Programmer’s Trick: Custom Number Rounding
Most programming languages have a function to round a number to the closest whole number using standard math rules. Anything fraction of a number < 1/2 typically rounds down and any fraction of a number >= 1/2 rounds up. In Visual Basic, there’s a “Round” function, C# has a “Round” method and Excel even has a “Round” function.
- 1.0 already a whole number, rounded value remains 1.0
- 1.25 rounds DOWN to 1.0
- 1.49 rounds DOWN to 1.0
- 1.5 rounds UP to 2.0
- 1.75 rounds UP to 2.0
- 2.0 already a whole number, rounded value remains 2.0
- …etc…
Some languages lisp AutoLISP, doesn’t have a function that behaves like this. Instead, AutoLISP had a “FIX” function that rounds down, regardless of the fractional component.
- 1.0 already a whole number, rounded down remains 1.0
- 1.25 rounded down becomes 1.0
- 1.49 rounded down becomes 1.0
- 1.5 rounded won becomes 1.0
- 1.75 rounded down becomes 1.0
- 2.0 already a whole number, rounded down remains 2.0
- …etc…
If you use a language like AutoLISP that only drops the fractional component of a number (essentially always rounding down) to function like real math rules, this is easily accomplished by simply adding 0.5 to the number before rounding. This changes the resulting rounded number to the same as traditional mathematics would round the numbers.
- 1.0 + 0.5 = 1.5 rounded down becomes 1.0
- 1.25 + 0.5 = 1.75 rounded down becomes 1.0
- 1.49 + 0.5 = 1.99 rounded down becomes 1.0
- 1.5 + 0.5 = 2.0 rounded down becomes 2.0
- 1.75 + 0.5 = 2.25 rounded down becomes 2.0
- 2.0 + 0.5 = 2.5 rounded down becomes 2.0
- …etc…
So far, this is quite simple. But what if you wanted to round to the nearest 1/8? Or 1/2? Again, many of the rounding functions in programming languages have the ability to round to a certain number of decimal places by specifying the number of decimal places as an argument to the rounding function. This works great on decimal values where you want to round to the nearest 1/10 (0.1), or 1/100 (0.01). However, this doesn’t work in other fraction that are not base 10. Rounding to the nearest 1/8 yields 3 decimals (0.125) but 2/8 (1/4) yields 2 decimal places (0.25) and 4/8 (1/2) yields in 1 decimal place (0.5). So how is this done?
Quite simply actually. You can use another technique which shifts the decimal. This moves the fractional component you want to keep to the left of the decimal and leaves the remaining fractional components to the right of the decimal where you can round them off. It sounds more complicated than it is. Let’s look at how this works by focusing on 1/8 (0.125).
What happens when we multiply 1/8 (0.125) by a factor of 8? We get 1.0 which when rounded, stays 1.0, we then divide by 8 again which shifts the decimal back to where it belongs and we end up with out original number as follows…
0.125 * 8 = 1.0 rounded stays 1.0 / 8 = 0.125 (1/8)
Now let’s try this when the number is slightly larger….
0.126 * 8 = 1.008 rounded becomes 1.0 / 8 = 0.125 (1/8)
The key is…if you want to round to the nearest 1/8, you “MULTIPLY by 8, ROUND, then DIVIDE by 8″. You can also use the inverse formula “DIVIDE by 1/8, ROUND, then MULTIPLY by 1/8″. Either formula works.
The same technique works if you want to round to the nearest 2 (even) or 3 (3, 6, 9, etc.).
- 0.25 / 2 = 0.125 becomes 0.0 * 2 = 0.0
- 0.5 / 2 = 0.25 rounded becomes 0.0 * 2 = 0.0
- 1.0 / 2 = 0.5 rounded becomes 1.0 * 2 = 2.0
- 1.99 / 2 = 0.995 rounded becomes 1.0 * 2 = 2.0
- 2.00 / 2 = 1.0 rounded becomes 1.0 * 2 = 2.0
- 2.99 / 2 = 1.495 rounded becomes 1.0 * 2 = 2.0
- 3.0 / 2 = 1.5 rounded becomes 2.0 * 2 = 4.0
- 3.5 / 2 = 1.75 rounded becomes 2.0 * 2 = 4.0
Using these techniques, you can quickly convert numbers into the rounded format of your liking, regardless of the programming language you use.