0

Here is my code.

led.cost=led.cost-((Ledger)mdisellList.get(ms)).cost;

Intial values of led.cost is 4119.7 and mdisellList.cost is 172.485. Both are double datatypes.

I've seen those values in that variables while debugging (no decimals after .7 or .485). No rounding of has done before this line. While subtracting 172.485 from 4119.7 it gives the result as 3947.2149999997 instead of 3947.215.

I want exact 3947.215 instead of 3947.2149999997.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197

3 Answers3

3

Unfortunately in these cases one has to use BigDecimal instead of double.

Doubles are a sum of (negative) powers of 2 (bits!), that is a decimal representation like 0.10 can only be approximated: 1/16 + 1/32 + ... . When calculating the deviation enlarges and becomes visible.

To use doubles, one would constantly have to use formatted output, DecimalFormat, (even a good thing for locales which use a decimal comma and for thousand separators). But one would need also constantly round things. And given tax and other laws, sometimes to 6 decimals and so on.

BigDecimal is an immutable value type. It needs a scale/precision to set, And has awkward add, subtractand multiply methods.

new BigDecimal("0.10"); // Works perfectly.
new BigDecimal(0.10); // Should not be used, looses precision 2,
                      // and has epsilon error.

And then there is the database side. Depending on the database system DECIMALS might be preferred above DOUBLE.

(The third alternative would be to use cents, long but that is circumstantial too.)

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
0

FINE! FINE! Peer pressure is in double.

IF you know how to handle doubles in Java, or if your project requirements don't require financial mathematics, then using doubles in Java is ok.

However, if you are not absolutely sure how floating point works, stay away from doubles or get hurt by trivial things such as

System.out.println(0.01 + 5.02);

IF you don't know how to handle doubles then the better choice is to stick to libraries which were designed specifically for this purpose, such as

http://en.wikipedia.org/wiki/Bignum
http://www.apfloat.org/
http://jscience.org/
java.math.*.

Alexandre Santos
  • 8,170
  • 10
  • 42
  • 64
  • 1
    I think you should reword your first sentence. `double` variables are OK to use for floating point calculation *if floating-point error is OK*. You should probably say something more like "Do NOT use doubles for floating-point calculation when accuracy is important" – awksp Jul 03 '14 at 06:24
  • 1
    This is very badly worded. You can write floating point algorithms without those libraries and still get the result - you just have to know how floating-point arithmetic works. – laune Jul 03 '14 at 06:29
  • 1
    Calculating with double values gives an accuracy of about 15 decimal digits. This is more than enough for most applications. – Henry Jul 03 '14 at 06:29
  • 2
    Large-scale simulations, where performance considerations outweigh "exact accuracy" considerations? I'd imagine that `double` precision is "good enough" for a lot of cases otherwise no one would use them... – awksp Jul 03 '14 at 06:30
  • 3
    The first line is the equivalent of saying "do not use floating point calculations for floating point calculations". – Mark Rotteveel Jul 03 '14 at 06:32
  • @user3616277 Financial mathematics must use *fixed-point* arithmetic, which is very much as you do it with pen and paper. Rounding of monetary values (e.g. for VAT) is typically defined by law. (java.math.BigDecimal is required.) – laune Jul 03 '14 at 06:34
0

You can convert your amount into smaller currency unit. Means 1 euro = 100 cent. If you have 0.01 euro make it as 1 Cent and perform calculation and convert them back to Euro by Using BigDecimal and rounding modes.

http://martinfowler.com/eaaCatalog/money.html

Bhushan
  • 567
  • 2
  • 5
  • 14
  • Eventually you'll run into calculations like 21% VAT, or interest rate 2.25%, so that you'll have to push the decimal point still farther to the right. And when you'll have to divide by 3 or 7, you'll be pushing forever and a day... ;-) – laune Jul 03 '14 at 06:52