Java rounding issues
I am using the following code to round the float value which is given as input. But i cant get it right. If i give $80 i should get $80.00 and if i give $40.009889 i should get $40.01. How do i do this ?
public class round { public static float round_this(float num) { //float num = 2.954165f; float round = Round(num,2); return round; } private static float Round(float Rval开发者_StackOverflow中文版, int Rpl) { float p = (float)Math.pow(10,Rpl); Rval = Rval * p; float tmp = Math.round(Rval); return (float)tmp/p; } }
This is why you don't use floats for money, because you get stuck in this game of 'Garbage In, Data Out'. Use java.math.BigDecimal instead. BigDecimal lets you specify a fixed-decimal value that isn't subject to representation problems.
(When I say don't use floats that includes doubles, it's the same issue.)
Here's an example. I create two BigDecimal numbers. For the first one I use the constructor that takes a floating-point number. For the first one I use the constructor that takes a string. In both cases the BigDecimal shows me what the number is that it holds:
groovy:000> f = new BigDecimal(1.01)
===> 1.0100000000000000088817841970012523233890533447265625
groovy:000> d = new BigDecimal("1.01")
===> 1.01
See this question for more explanation, also there's another question with a good answer here.
From The Floating-Point Guide:
Why don’t my numbers, like 0.1 + 0.2 add up to a nice round 0.3, and instead I get a weird result like 0.30000000000000004?
Because internally, computers use a format (binary floating-point) that cannot accurately represent a number like 0.1, 0.2 or 0.3 at all.
When the code is compiled or interpreted, your “0.1” is already rounded to the nearest number in that format, which results in a small rounding error even before the calculation happens.
Use BigDecimal class instead of float.
And use Java code like this:
BigDecimal bd = new BigDecimal(floatVal);
bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
I wouldn't use float
, I suggest using double
or int
or long
or (if you have to) BigDecimal
private static final long[] TENS = new long[19];
static {
TENS[0] = 1;
for (int i = 1; i < TENS.length; i++) TENS[i] = TENS[i - 1] * 10;
}
public static double round(double x, int precision) {
long tens = TENS[precision];
long unscaled = (long) (x < 0 ? x * tens - 0.5 : x * tens + 0.5);
return (double) unscaled / tens;
}
This does not give a precise answer for all fractions as that is not possible with floating point, however it will give you an answer which will print correctly.
double num = 2.954165;
double round = round(num, 2);
System.out.println(round);
prints
2.95
This would do it.
public static void main(String[] args) {
double d = 12.349678;
int r = (int) Math.round(d*100);
double f = r / 100.0;
System.out.println(f);
}
You can short this method, it's easy to understand that's why I have written like this
精彩评论