# Compounding Double Error

# Compounding Double Error

Join the DZone community and get the full member experience.

Join For Free**Don’t let inefficiencies in software testing lead to delayed deployments and poor quality products. Get the 90 Days to Better QA Guide by Rainforest QA for best practices to avoid these common pitfalls.**

In a previous article, I outlined why BigDecimal is not the answer most of the time. While it is possible to construct situations where double produces an error, it is also just as easy to construct situations were BigDecimal get an error.

### BigDecimal is easier to get right, but easier to get wrong.

The anecdotal evidence is that junior developers don't have as much trouble getting BigDecimal right as they do getting double with rounding right. However, I am sceptical of this because in BigDecimal it is much easier for an error to go unnoticed as well.

Lets take this example where double produces an incorrect answer.

double d = 1.00; d /= 49; d *= 49 * 2; System.out.println("d=" + d); BigDecimal bd = BigDecimal.ONE; bd = bd .divide(BigDecimal.valueOf(49), 2, BigDecimal.ROUND_HALF_UP); bd = bd.multiply(BigDecimal.valueOf(49*2)); System.out.println("bd=" + bd);

d=1.9999999999999998 bd=1.96

### You have to ensure numbers are real and use rounding.

double interest = 0.0005; BigDecimal interestBD = BigDecimal.valueOf(interest); double amount = 1e6; BigDecimal amountBD = BigDecimal.valueOf(amount); BigDecimal amountBD2 = BigDecimal.valueOf(amount); long i = 0; do { System.out.printf("%,d: BigDecimal: $%s, BigDecimal: $%s%n", i, amountBD, amountBD2); i++; amountBD = amountBD.add(amountBD.multiply(interestBD).setScale(2, BigDecimal.ROUND_HALF_UP)); amountBD2 = amountBD2.add(amountBD2.multiply(interestBD)); } while (amountBD2.subtract(amountBD).abs().compareTo(BigDecimal.valueOf(0.01)) < 0); System.out.printf("After %,d iterations the error was 1 cent and you owe %s%n", i, amountBD);

8: BigDecimal: $1004007.00, BigDecimal: $1004007.00700437675043756250390625000000000000000

### double eventually has a representation error

double interest = 0.0005; BigDecimal interestBD = BigDecimal.valueOf(interest); double amount = 1e6; BigDecimal amountBD = BigDecimal.valueOf(amount); long i = 0; do { System.out.printf("%,d: double: $%.2f, BigDecimal: $%s%n", i, amount, amountBD); i++; amount = round2(amount + amount * interest); amountBD = amountBD.add(amountBD.multiply(interestBD).setScale(2, BigDecimal.ROUND_HALF_UP)); } while (BigDecimal.valueOf(amount).subtract(amountBD).abs().compareTo(BigDecimal.valueOf(0.01)) < 0); System.out.printf("After %,d iterations the error was 1 cent and you owe %s%n", i, amountBD);

22,473: double: $75636308370.01, BigDecimal: $75636308370.01 After 22,474 iterations the error was 1 cent and you owe 75674126524.20

### Conclusion

**Discover how to optimize your DevOps workflows with our on-demand QA solution, brought to you in partnership with Rainforest QA. **

Published at DZone with permission of Peter Lawrey , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

## {{ parent.title || parent.header.title}}

## {{ parent.tldr }}

## {{ parent.linkDescription }}

{{ parent.urlSource.name }}