We have the following legacy function in our application:
public static Double getSum( List<Double> values ) {
Double sum = null;
for( Double value : values ) {
if ( value != null ) {
if ( sum == null ) {
sum = value;
} else {
sum += value;
}
}
}
return sum;
}
I am calling it with main using following snippet :-
public static void main( String[] args ) {
Double sum = getSum( Arrays.asList( -49.66, -42.02, 42.02, 49.66 ) );
System.out.println( "Sum=" + sum );
}
It is supposed to give output as 0. But it is giving result as -7.105427357601002E-15. When I tried to debug it, the first two values are being added properly but after adding the third value, a decimal component is getting automatically and result after adding third value is -49.660000000000004. Can anybody please point out why this would happen? We are anyways going to replace it
values.stream().filter( value -> value != null ).mapToDouble( Double::doubleValue ).sum();
But, I still would like to understand the reason behind this discrepancy in the original method
Edit:- I tried the solutions in the mentioned link. I changed my method to use BigDecimal instead of Double. But the same error persists. Updated code:-
public static BigDecimal getSumBigDecimal( List<BigDecimal> values ) {
BigDecimal sum = null;
for( BigDecimal value : values ) {
if ( value != null ) {
if ( sum == null ) {
sum = value;
} else {
sum = sum.add( value );
}
}
}
return sum;
}
Updated main method:-
public static void main( String[] args ) {
// Double sum = getSum( Arrays.asList( -49.66, -42.02, 42.02, 49.66, 0.11, -0.105 ) );
BigDecimal sum = getSumBigDecimal(
Arrays
.asList( new BigDecimal( -49.66 ), new BigDecimal( -42.02 ), new BigDecimal( 42.02 ), new BigDecimal( 49.66 ), new BigDecimal( 0.11 ), new BigDecimal( -0.105 ) ) );
System.out.println( "Sum=" + sum );
}
Getting output as 0.00500000000000000444089209850062616169452667236328125000 even with BigDecimal