Seems like the subtraction is triggering some kind of issue and the resulting value is wrong.
double tempCommission = targetPremium.doubleValue()*rate.doubleValue()/100d;
78.75 = 787.5 * 10.0/100d
double netToCompany = targetPremium.doubleValue() - tempCommission;
708.75 = 787.5 - 78.75
double dCommission = request.getPremium().doubleValue() - netToCompany;
877.8499999999999 = 1586.6 - 708.75
The resulting expected value would be 877.85.
What should be done to ensure the correct calculation?
To control the precision of floating point arithmetic, you should use java.math.BigDecimal. Read The need for BigDecimal by John Zukowski for more information.
Given your example, the last line would be as following using BigDecimal.
import java.math.BigDecimal;
BigDecimal premium = BigDecimal.valueOf("1586.6");
BigDecimal netToCompany = BigDecimal.valueOf("708.75");
BigDecimal commission = premium.subtract(netToCompany);
System.out.println(commission + " = " + premium + " - " + netToCompany);
This results in the following output.
877.85 = 1586.6 - 708.75
As the previous answers stated, this is a consequence of doing floating point arithmetic.
As a previous poster suggested, When you are doing numeric calculations, use java.math.BigDecimal
.
However, there is a gotcha to using BigDecimal
. When you are converting from the double value to a BigDecimal
, you have a choice of using a new BigDecimal(double)
constructor or the BigDecimal.valueOf(double)
static factory method. Use the static factory method.
The double constructor converts the entire precision of the double
to a BigDecimal
while the static factory effectively converts it to a String
, then converts that to a BigDecimal
.
This becomes relevant when you are running into those subtle rounding errors. A number might display as .585, but internally its value is '0.58499999999999996447286321199499070644378662109375'. If you used the BigDecimal
constructor, you would get the number that is NOT equal to 0.585, while the static method would give you a value equal to 0.585.
double value = 0.585; System.out.println(new BigDecimal(value)); System.out.println(BigDecimal.valueOf(value));
on my system gives
0.58499999999999996447286321199499070644378662109375 0.585
Another example:
double d = 0;
for (int i = 1; i <= 10; i++) {
d += 0.1;
}
System.out.println(d); // prints 0.9999999999999999 not 1.0
Use BigDecimal instead.
EDIT:
Also, just to point out this isn't a 'Java' rounding issue. Other languages exhibit similar (though not necessarily consistent) behaviour. Java at least guarantees consistent behaviour in this regard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With