2

Possible Duplicate:
Double calculation producing odd result

I'm writing a program in Java that deals with a lot of double arithmetic. I eventually get to the point where I need to add 0.6666666666666666 and -0.666666666666667. However, the answer that I get is -3.3306690738754696E-16.

In other words,

double d1 = 0.6666666666666666;
double d2 = -0.666666666666667;
System.out.println(d1 + d2);

prints out "-3.3306690738754696E-16". Why is this happening?

Thank you in advance.

Community
  • 1
  • 1
Arepa Slayer
  • 443
  • 1
  • 7
  • 20
  • 5
    You are limited by the `double` type. It does not store exact decimal fields, but is an IEEE 754 8-byte floating point number. – fge Jan 06 '13 at 23:40
  • 1
    You are right, they are similar. Feel free to report the question as a duplicate. Sorry about that. – Arepa Slayer Jan 07 '13 at 00:02
  • 2
    See [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html). – Andrew Thompson Jan 07 '13 at 00:11

2 Answers2

6

doubles are not perfectly accurate, and not every decimal can be perfectly represented as a double (see this). For all practical purposes, -3.3306690738754696E-16 is 0 *. However, if you need more precision, use BigDecimal. Keep in mind that this alternative will not be nearly as efficient as using primitive doubles. It's up to you to decide if you need this level of accuracy and to make a choice accordingly.

*: Evidently, that number is not exactly zero, but for the majority of real-world calculations and computations, a value that small would be inconsiderable. In meters, this value is smaller than the diameter of protons and neutrons - i.e. very very small. That's what I mean by "for all practical purposes".

arshajii
  • 127,459
  • 24
  • 238
  • 287
1

double values cannot represent all values precisely and this is such an example. You can use BigDecimal instead:

BigDecimal bd1 = new BigDecimal("0.6666666666666666");
BigDecimal bd2 = new BigDecimal("-0.666666666666667");
System.out.println(bd1.add(bd2));

Output:

-4E-16
Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • Interesting, I always thought of doubles as the ultimate solution for floating-point operations. Thanks a lot! – Arepa Slayer Jan 06 '13 at 23:49
  • 4
    @fpele `double` still *is* the ultimate solution for *efficient* floating point on current CPUs. `BigDecimal` is a fixed point type, not floating. – us2012 Jan 07 '13 at 00:08
  • 1
    @us2012: Are you sure about that? It looks a lot like floating point to me. For example, the `scale` of a product is typically the sum of the scales of the multiplicands; with fixed point, I'd expect the result to have the same scale as the inputs. – Mark Dickinson Jan 07 '13 at 15:19
  • @MarkDickinson You're right, I got the terminology mixed up. The point I was trying to make is that `BigDecimal` does not *behave* like we expect floating point numbers to behave. The right term is of course *arbitrary precision*, which comes at a huge performance cost, so that `double` still remains the best solution whenever you don't explicitly need arbitrary precision. – us2012 Jan 07 '13 at 15:34
  • @us2012: True enough ... – Mark Dickinson Jan 07 '13 at 15:45