Please comment me freely. What was wrong in the following program. It is giving different round result.
public class Test {
public static String round(double value, int places) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.toPlainString();
}
public static void main(String[] args) throws Exception {
double value1 = 1.1234565;
System.out.println(round(value1, 6));
double value2 = 1.1235;
System.out.println(round(value2, 3));
}
}
Why it is out put like that?
1.123457
1.123 --> Actually, I expect 1.124
In Doc(eclipse)
You're calling the BigDecimal(double)
constructor. That's documented as:
Translates a double into a BigDecimal which is the exact decimal representation of the double's binary floating-point value. The scale of the returned BigDecimal is the smallest value such that (10scale × val) is an integer.
The notes are illuminating too, and I suggest you read them.
The value you're passing in is exactly 1.12349999999999994315658113919198513031005859375, as that's the closest double
to 1.1235. You can see that if you print out bd.toPlainString()
before calling setScale
. Therefore, that isn't half-way between 1.123 and 1.124 - it's closest to 1.123.
If you want a BigDecimal
value of exactly 1.1235, I suggest you pass it as a String
instead:
import java.math.*;
public class Test {
public static String round(String value, int places) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.toPlainString();
}
public static void main(String[] args) throws Exception {
String value1 = "1.1234565";
System.out.println(round(value1, 6));
String value2 = "1.1235";
System.out.println(round(value2, 3));
}
}
Alternatively you could use BigDecimal.valueOf(double)
instead of new BigDecimal(double)
- but then you still have the problem that you've converted your real original source data (the text in your source code) into a binary floating point number first, potentially losing information.
See more on this question at Stackoverflow