It appears that HALF_EVEN
rounding mode works differently in Java DecimalFormat
than BigDecimal
. Is there any way to make the DecimalFormat
be consistent?
// Using BigDecimal scale
System.out.println("Big decimal scale (HALF_EVEN) of 21.255 ==> " + new BigDecimal("21.255").setScale(2, RoundingMode.HALF_EVEN));
System.out.println("Big decimal scale (HALF_EVEN) of 21.265 ==> " + new BigDecimal("21.265").setScale(2, RoundingMode.HALF_EVEN));
// Using DecimalFormat
DecimalFormat cdf = new DecimalFormat("#,##0.00");
cdf.setRoundingMode(RoundingMode.HALF_EVEN); // default anyway
System.out.println("Decimal format (HALF_EVEN) of 21.255 ==> " + cdf.format(21.255));
System.out.println("Decimal format (HALF_EVEN) of 21.265 ==> " + cdf.format(21.265));
Output:
Big decimal scale (HALF_EVEN) of 21.255 ==> 21.26
Big decimal scale (HALF_EVEN) of 21.265 ==> 21.26
Decimal format (HALF_EVEN) of 21.255 ==> 21.25
Decimal format (HALF_EVEN) of 21.265 ==> 21.27
As said in the comment, if you try:
Double double1 = new Double(21.255);
BigDecimal bigDecimal1 = new BigDecimal(double1);
System.out.println(bigDecimal1); //21.254999999999999005240169935859739780426025390625
Double double2 = new Double(21.265);
BigDecimal bigDecimal2 = new BigDecimal(double2);
System.out.println(bigDecimal2); //21.2650000000000005684341886080801486968994140625
You will find that:
double 21.255
is a little less than 21.255
double 21.265
is a little greater than 21.265
You can initiate the input as BigDecimal
when using DecimalFormat
to avoid losing accuracy:
System.out.println("Decimal format (HALF_EVEN) of 21.255 ==> " + cdf.format(new BigDecimal("21.255")));
//21.26
System.out.println("Decimal format (HALF_EVEN) of 21.265 ==> " + cdf.format(new BigDecimal("21.265")));
//21.26
I just ran some tests : using @Mark Rotteveel solution :
cdf.format(new BigDecimal(21.255))
Big decimal scale (HALF_EVEN) of 21.255 ==> 21.26
Big decimal scale (HALF_EVEN) of 21.265 ==> 21.26
Decimal format (HALF_EVEN) of 21.255 ==> 21,25
Decimal format (HALF_EVEN) of 21.265 ==> 21,27
using the BigDecimal
String constructor:
cdf.format(new BigDecimal("21.255"))
Big decimal scale (HALF_EVEN) of 21.255 ==> 21.26
Big decimal scale (HALF_EVEN) of 21.265 ==> 21.26
Decimal format (HALF_EVEN) of 21.255 ==> 21,26
Decimal format (HALF_EVEN) of 21.265 ==> 21,26
So clearly, you have to use the String
constructor to get the right result
The value of the double 21.255
is not exactly 21.255, it is actually closer to 21.25499999...
, which means even with rounding mode HALF_EVEN
, it will round down to 21.25
. Similarly the double 21.265
is actually closer to 21.26500000000000056...
which means it will round up.
You can get the exact same behavior as DecimalFormat
by using new BigDecimal(double)
instead of new BigDecimal(String)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.