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,420
  • 11
  • 42
  • 71

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
  • 14,673
  • 7
  • 54
  • 81
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
  • 513,304
  • 74
  • 731
  • 1,106
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
  • 250,062
  • 96
  • 490
  • 643
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
  • 24,095
  • 8
  • 74
  • 100