Reputation: 693
I am writing a function round: static float round(float number, precision){}
The function should work like this: round(12.3456f, 3) = 12.345
My definition of function is like this:
public static float round(float value, int precision) {
float result;
if(precision <= 0){
throw new RuntimeException("Precision can not be zero or less");
}
int number = (int) power(10,precision);
value = value * number;
result = (float)Math.round(value)/number;
return result;
}
But the issue is that, my unit test case for this function doesn't pass,
public void mathTestNew() {
assertEquals("MathTest",12.341,OOTBFunctions.round(12.3416f,3));
}
The result is junit.framework.AssertionFailedError: MathTest expected:<12.341> but was:<12.342>
I am not sure how to overcome this error. I am not sure if BigDecimal will help me in this.
Upvotes: 3
Views: 1238
Reputation: 6665
If you did want to use BigDecimal
:
public static float round(float value, int precision) {
if (precision <= 0) {
throw new IllegalArgumentException("Precision cannot be zero or less.");
}
BigDecimal decimal = BigDecimal.valueOf(value);
return decimal.setScale(precision, RoundingMode.FLOOR).floatValue();
}
You may lose accuracy when converting from BigDecimal
to float
, so if accuracy is a must, do not convert; keep the value as a BigDecimal
.
As mentioned in other answers, float
is an approximation of a base 10 number. The following demonstrates just that:
System.out.println(BigDecimal.valueOf(12.3416f)); // outputs 12.34160041809082
System.out.println(new BigDecimal("12.3416")); // outputs 12.3416
Upvotes: 2
Reputation: 106401
Rounding normally occurs towards the nearest integer. So 12.3416
is correctly rounded to 12.342
If you want the rounding behaviour you seem to be asking for (where the number is rounded down towards negative infinity) then you should use Math.floor(x) instead of Math.round(x)
Also be careful with rounding floats / doubles as they both suffer from numerical inaccuracy. If you really want high accuracy on decimal places, you may be better using BigDecimal instead.
Upvotes: 4
Reputation: 311048
You can't write such a method. Floating point doesn't have decimal places, it has binary places. Ergo you cannot round to a specified number of decimal places. If you want decimmal places you must use a decimal radix, i.e. BigDecimal, or DecimalFormat. Apart from the error in expectation noted by @ColeJohnson, code like you have written will fail in over 90% of cases.
Upvotes: 0
Reputation: 9425
12.3416
rounded is 12.342
. There in lies your problem. You probably want Math.Floor
instead. I would recomend against constantly multiplying as that can ruin the number. However, by 10 does not lower precision.
Upvotes: 1
Reputation: 272772
Math.round
is "round-to-nearest". You probably want Math.floor
.
Upvotes: 3