Win a copy of The Way of the Web Tester: A Beginner's Guide to Automating Tests this week in the Testing forum!

# Is it a good strategy to use a static method for rounding?

Eric Barnhill
Rancher
Posts: 233
Hi,

I'm pretty inexperienced with code strategy so I just wondered if this was a good one. For something like rounding, in which in my experience a few steps are needed to get around Java arithmetic issues, is a static method that takes the necessary few steps a good way to handle the difficulty.

So my code is

Run using

Output obviously is

Just wondering if my idea of a static method is a good way to handle this situation? In my package, I would just stick it in a class of static utility methods. Thanks for any feedback!

Bill Clar
Ranch Hand
Posts: 163
I like the abstraction provided by your threeStepRound function, but I would use a BigDecimal instead of primitives arithmetic.

Campbell Ritchie
Sheriff
Posts: 50699
83
Agree.
Agree that is a function and can therefore be a static method. In fact that sort of thing should probably be in a utility class.You can overload that method to take floats. Note you will get all sorts of imprecision with floating‑point arithmetic, which is why Bill Clar recommends decimal arithmetic. The output of this code:-…will not show any signs of rounding. It will most probably start with 1234567890, though. The second value of d might be different from the original value.

Jayesh A Lalwani
Rancher
Posts: 2762
32
Are you rounding the number for processing.. or are you rounding it for display. Personally, I would never round numbers until they have to be displayed, and then I would just do it in the Formatter

Campbell Ritchie
Sheriff
Posts: 50699
83
Jayesh A Lalwani wrote:. . . I would never round numbers until they have to be displayed, and then I would just do it in the Formatter
That does not constitute real rounding; you are not altering the value, but simply the way it is displayed.
But you are right that rounding would introduce new imprecision.

Stevens Miller
Bartender
Posts: 1313
25
Eric Barnhill wrote:Hi,

I'm pretty inexperienced with code strategy so I just wondered if this was a good one. For something like rounding, in which in my experience a few steps are needed to get around Java arithmetic issues, is a static method that takes the necessary few steps a good way to handle the difficulty.

Could you say a bit more about what you mean by, "Java arithmetic issues"? At line 7 of your code, your output is 10 because Math.round(value * 1000) returns a long (when value is a double). Dividing a long by another long (in this case, 1000), yields an integer result, (in this case, 10). However, if you change the divisor in line 7 from a long to a double, which you can do with the insertion of a decimal point, thus:

the long returned by Math.round is coerced into a double. When one double is divided by another, the result is also a double. In this case, the output of the program becomes this:

Now, Java doubles do a pretty good job of faking real numbers (better than floats), but even they have their limits. Consider this:

I get this output:

If doubles were pure real numbers, that should have been 1.0. But no finite state machine can represent all real numbers. Which means, even all the way back to your initial input, the very first numeric value stored in your "value" variable may not have been (and probably wasn't) exactly 10.79865. In an extreme case, you could input a string with three decimal places, multiply it by 1000, divide it back again, and discover that the inherent rounding of doubles themselves had thrown your last digit off by one.

I don't have a string at hand that can show you this (and Java's ability to cope with this issue may well be subtler than I know), but consider these lines of code:

Output ought to be 0.0, right? Nope, it's this:

Which is pretty close to zero, but it wouldn't return true if you coded this:

All of which means that, if you need accuracy to some number of decimal places (greater than zero, that is), that you can absolutely rely on, don't represent your value at any point in your calculations as a double (or a float, of course). From that very first assignment to such a variable, you are losing some amount of precision (there are exceptional cases where a double can store a real number with absolute precision, but there are an infinite number of real numbers that it cannot store with infinite precision). Instead, either find a way to represent your data entirely in an integer format (for example, if you are sure you only ever need three decimal places, you could do all your calculations in integers scaled by 1,000), or use one of the classes designed for this (like BigDecimal, I would guess, though I never use it, myself).

HTH