Coding Math: Mini #8 – Rounding

This is Coding Maths Mini #8 – Rounding Shout out to my British viewers who love their
maths. Today we’re going to talk about rounding numbers,
a subject that a lot of people take for granted, but you can do some pretty cool things with.
Rounding is simply a function that takes an input number and gives back an output number
that is either the same as, or somewhere in the vicinity of the input. The most common
type of rounding is to round to the nearest integer. If you have 7.4 for example, you’re
in between the integers 7 and 8. You’re closest to 7, so that’s your answer. If you were at
7.8, you’d be closer to 8 and that would be your answer. Of course 7.5 is dead center
between the two, so the convention is usually that if the fraction is 0.5 or higher, round
up, otherwise round down. This is all stuff you should already know
from grade school. But it’s worth mentioning just to make sure we’re all on the same page. Now, most programming languages have some
kind of math library that usually contains three standard rounding functions. I’ll describe
the JavaScript versions, but in most languages, you’ll find nearly identical functions. Math.floor rounds down to the next lowest
integer. So 7.0 will round to 7, as will 7.1, 7.5 and 7.999. If you want to see an example
of Math.floor in action, check out Mini #5 on random numbers. This is usually the same
thing as converting or casting a floating point number to an integer, which usually
just chops off the fractional part of the number. Math.ceil or ceiling does the opposite, always
rounding to the next highest integer. 7.0 would still round to 7, but 7-point-anything
will always round up to 8. 7.9, 7.4, 7.0001 all go to 8. Then there’s the old standard, Math.round,
which rounds to the closest integer, using the .5 and higher rule. So 7.1 would round
down to 7 and 7.8 would round up to 8. Now many programmers go along with these built
in functions and do just fine, but we’re going to create a couple more rounding functions
that are super powerful. The first one allows you to round not just
to integers, but to any number of decimal places, or even to the nearest 10, 100, 1000
etc. Now of course, when you’re dealing with long
floating point numbers, you often need all those digits for accuracy in calculations.
But there are plenty of times you don’t need them. Particularly when you you are displaying
the value to a user. For example, if you’re making a slider control that has min and max
values of 0 and 1, you probably don’t need to display the value of that slider to 10
decimal places. One or two decimals would probably be fine. Another obvious example is anything to do
with money. Say you’re doing a shopping cart app. A user buys something for 7.99 (pounds)
with a 5% VAT. Another shout out to the Brits there. The total would be 8.3895. But you
can’t charge that amount. You have to round it to the nearest cent: 8.39. Now your built
in math functions don’t help much because they’ll only round to the nearest integer. So what you do is multiply by 100. This gives
you 838.95. THEN you round, which gives you 839, then you divide by 100 to get 8.39. Now, say we want to display the value of PI,
which is 3.141592653589793. But you only want to display it to 3 places. Multiply by 1000
which gives you 3141.592653589793. Round to get 3142 and divide by 1000 to get 3.142. If you want it to one place, multiply by 10,
round, then divide by 10 and youl’ll get 3.1. So, we have 10 for one decimal place, 100
for two places, 1000 for three. Of course, 10,000 would give you four places, and so
on. Now here’s a trick: 10 to the power of 1 is 10, 10 to the power of 2 is 100, to the
power of 3 is 1000, and 10 to the power of 4 is 10,000, and so on. This matches up perfectly
to the number of places we want to round to. So we can make a roundToPlaces function. I’ll
add it right to the utils library. function roundToPlaces(value, places) {
var mult=Math.pow(10, places); return Math.round(value * mult) / mult;
} This takes the value that you want to round,
and the number of places you want to round it to. First it calculates a mult variable.
This uses Math.pow to raise 10 to the specified power. So if places is 2, we’re saying Math.pow(10,
2) which is 10 to the power of 2 or 10 times 10 or 100. Then we multiply the value by that mult variable,
round it, divide it by mult and return the result. In this simple test file, I’m just going to
log the value of PI to 1, 3, and 5 places. And you see this gives us 3.1, 3.142, 3.14159. An interesting thing about this function is
that you can feed it negative place values to round to powers of 10. For example, -1
will round the input value to the nearest 10, -2 to the nearest 100 and -3 to the nearest
1000. And passing in 0 simply rounds to the nearest 1, which is the same as using Math.round
directly. Here’s an example of rounding a large number
to 10s, 100s and 1000s. And here’s the result. So this function will let you round to any
decimal or power of 10, but sometimes you need to round to other values. A great example
is a “snap-to-grid” function. Say you have a 40-pixel grid and you want to snap objects
so that they always align with this grid. Well, we can just lose all the Math.pow stuff
and switch the order of things around to create a roundNearest function. function roundNearest(value, nearest) {
return Math.round(value / nearest) * nearest; } So in the grid example, say the current value
was 113 and we want to round that to the nearest multiple of 40 to align with the grid. We
divide value, 113, by 40 and we get 2.825. Rounded, is 3. Multiply 3 by 40 to get 120.
And that’s the multiple of 40 that’s closest to 113. Here’s an example file. I set a gridSize of
40 pixels. Then I listen for mousemove to get the current mouse coordinates. I draw
a grid using this drawGrid function which just draws a bunch of horizontal and vertical
lines spaced using gridSize. Then I use roundNearest(event.clientX, gridSize) to get a rounded x value and I do
the same with clientY to get a rounded y value. Finally I just draw a circle at that x, y
position. We run that… and see that no matter where I move the mouse,
it draws a circle centered on one of the grid coordinates. Try changing gridSize and you’ll
see the new grid drawn to that size and the circle will still automatically snap to that
new grid. So a couple of new utility functions. I’m
sure you’ll find these very useful. See you next time.