The first thing to notice is a pseudo-relation between rounding and truncating. Notice that:
Where a square bracket '[' denotes inclusion in the range, and a parenthesis '(' denotes non-inclusion in the range -- ie. [3.0, 4.0) is the range of all numbers between 3 and 4, including 3 but not including 4.
In simplest terms, truncation means to chop off the decimal portion of a number. This means:
And so on.
Well, this is a really simple task for a person to perform. It involves writing down the number you want to truncate in pencil, then erasing everything after the decimal place :)
Well, the algorithm differs slightly depending on whether you are truncating a positive value (greater than or equal to zero) or a negative value (less than zero).
In the interest of keeping things simple, let's just discuss the algorithm for truncating positive numbers (and the really motivated among you can see if you can figure out an algorithm for truncating negative numbers).
Notice that the domains on the truncation function and round function for any given return value are offset by exactly 0.5. Cool, huh?
So, if I had a value that would truncate to 5 (say 5.75, for example), I could simply subtract 0.5 from the value, and my new value (5.25 in the example) would round to 5.
So, an easy way to truncate a positive value is to simply subtract 0.5 from it and then round it.
So, the natural next question is, "How can I do this task in Java?" Thankfully, it's very simple :)
Since the Math.round method accepts a float value as an argument, this entire algorithm can be performed in a single step:
truncated = Math.round(nontruncated - 0.5f);
Points of note in the above line of code are:
The algorithm of subtracting 0.5 from a value and then rounding it (which truncates a positive number) actually has so many uses that Java has been nice enough to include a method in its standard library that will do it for you.
In fact, in mathematics it is denoted as the "floor" function.
So, naturally, it has been included as a static method in the Math class called floor.
However, unlike the algorithm we developed above that takes a positive float and truncates it into an int value, the floor function both receives and returns a double value (you can confirm this in the Java Class Documentation).
Its sister function, "ceiling," performs a similar task: It adds 0.5 to a value and then rounds it (hint: this has something to do with how you would truncate a negative value).
Neat stuff, eh? Check out the Java Class Documentation, and try playing around with these functions when you have some spare time.
Now let's look at the algorithm for rounding a float value to two decimal places.
It is a process that returns the closest finite number expressed to two decimal places. This means:
And so on.
The first thing to notice when performing this task is that the process is nearly identical to rounding a decimal value to the nearest whole number, except the entire process is shifted over by two decimal places.
To explain briefly how a human would perform this task:
The great thing about working in Java is that, with the methods provided to you in the Math class, you don't even need to think that much to round a number to two decimal places!
Remember our initial observation that rounding a number to two decimal places is identical to rounding a number to the nearest whole, except the process is shifted by two decimal places? Let's take advantage of that fact.
Looking at the Java Class Documentation, you will see that in the Math class, there is a static method called round that takes a float as an argument and returns the closest int value (in other words, it rounds the float to a whole number int).
This is almost what we want to do -- except it rounds to the wrong precision. But, there is an easy way around this. Think for a moment; what would happen if we multiplied our float value by 100, then rounded it, then divided by 100?
Try this process with a few example numbers, and you'll quickly see what we have accomplished. We shift the decimal two places to the right by multiplying by 100, which results in the round method returning our number with the required number of digits to the left of the decimal. Then, we divide by 100 to shift the decimal place two places to the left again, yielding our original number rounded to two decimal places.
For example:
Much like the previous example, this algorithm is very simple to write in Java:
roundedToTwoDecimals = Math.round(unrounded*100)/100f;
Points of note in the above line of code are:
Math.round(unrounded*100)
, is an int as implied above. This is because Math.round's argument is a float, which means Math.round will return an int. Dividing an int by a float--in this case the divisor, 100f--returns a float. Thus, roundedToTwoDecimals must be a float for both compatibilitity, and to maintain the decimal places.