2

i am trying to financial app, where sum of credit and debit is 0

Why this is like this

scala> 7595.00-8544.38+949.38
res7: Double = 7.958078640513122E-13

but when sorted and added

scala> 7595.00+949.38-8544.38
res8: Double = 0.0

well the problem is numbers are at random but they always sum upto to zero

i did same with node and found same results. what is the problem.

i wrote this function it works

def sum(xs: List[Double]): Double = {
    xs match {
      case x :: tail => BigDecimal(x +  sum(tail)).setScale(2,BigDecimal.RoundingMode.HALF_UP).toDouble 
      case Nil => 0
    } 
}

it's strange though..

Cœur
  • 37,241
  • 25
  • 195
  • 267
AmeyChavan
  • 362
  • 1
  • 2
  • 14

2 Answers2

4

Floating point numbers are not exact representations of the underlying values. This is just a fact of how floating point numbers are encoded in binary.

For more information, check out the wikipedia article.

If you want exactness, use BigDecimal:

 scala> BigDecimal(759500,2) - BigDecimal(854438,2) + BigDecimal(94938,2)
 res1: scala.math.BigDecimal = 0.00
dhg
  • 52,383
  • 8
  • 123
  • 144
  • Thanks ,i prefer scala> BigDecimal(7595.00) - BigDecimal(8544.38) + BigDecimal(949.38) as the amount can be in one or two decimal – AmeyChavan Aug 01 '14 at 07:45
  • @ameychavan, don't do that because if you create a BigDouble out of a floating point number, then you might just be creating a BigDouble that already has the rounding error in it. E.g. `BigDecimal(1.1+2.2)`. – dhg Aug 01 '14 at 07:47
  • ,i'm not using double, but transforming right from the string i get from the inputstream – AmeyChavan Aug 01 '14 at 07:52
  • Uhh, The `8544.38` in `BigDecimal(8544.38)` is a double... But yeah, going from a string is fine. – dhg Aug 01 '14 at 08:02
4

This is why you should never use floating-point math for money. What you have there is a rounding error.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152