4

I am building a web app in Java that does math and shows steps to the user. When doing basic arithmetic with decimals I often get the messy in accurate outputs.

Here is my problem:

double a = 0.15;
double b = 0.01;
System.out.println(a - b);
// outputs 0.13999999999999999

float a = 0.15;
float b = 0.01;
System.out.println(a - b);
// outputs 0.14

float a = 0.16f;
float b = 0.01f;
System.out.println(a - b);
// outputs 0.14999999

double a = 0.16;
double b = 0.01;
System.out.println(a - b);
// outputs 0.15

Neither is reliable for complete accuracy. Is there a numeric class that is more precise or should I just round the values off?

Patrick Lorio
  • 5,520
  • 11
  • 45
  • 74

4 Answers4

6

You can use BigDecimal for this. It's ugly, but it works:

BigDecimal a = new BigDecimal("0.15");
BigDecimal b = new BigDecimal("0.01");
System.out.println(a.subtract(b));

Be sure to construct them either with a String parameter, or with the valueOf method, like this:

BigDecimal x = new BigDecimal("0.15");   // This is ok
BigDecimal x = BigDecimal.valueOf(0.15); // This is also ok

And not with a double parameter, like this:

BigDecimal x = new BigDecimal(0.15); // DON'T DO THIS

Because if you pass in a double, you will also pass in double's inaccuracy into the new BigDecimal instance. If you pass in a String, BigDecimal will know™ and do the right thing™.

jqno
  • 15,133
  • 7
  • 57
  • 84
2

You need to apply a sensible round when using double. If you do you can get 15 digits of accuracy which is more than enough in most cases.

double a = 0.15;
double b = 0.01;
System.out.printf("%.2f%n", a - b);

double a2 = 0.16;
double b2 = 0.01;
System.out.printf("%.2f%n", a2 - b2);

prints

0.14
0.15
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
1

How about BigDecimal?

Will not be completely accurate for all divisions, though (such as 1/3). For that you'd need fractions, which is not part of the JDK, but easy to implement, for example as two integers (or BigIntegers).

Community
  • 1
  • 1
Thilo
  • 257,207
  • 101
  • 511
  • 656
0
  BigDecimal  a = new BigDecimal(".15");
  BigDecimal  b = new BigDecimal(".01"),
  BigDecimal  c = new BigDecimal(0);

  c = a.subtract(b);      
  System.out.println(c);
Sumit Singh
  • 15,743
  • 6
  • 59
  • 89