0

I'm getting an invalid calculation result when using the double type in Delphi XE2. Below is code to a very simple calculation that should result in zero. Instead, it is returning -1.13686837721616E-13 which is incorrect.

var
  dblValue1, dblValue2, dblValue3, dblTotal: double;
begin
  try
    dblValue1 := 1671.37;
    dblValue2 := 871.37;
    dblValue3 := 800.00;

    dblTotal := (dblValue1 - dblValue3);
    dblTotal := (dblTotal - dblValue2);
    Write(FloatToStr(dblTotal));
    ReadLn;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

This fails the same way with either a 32 or 64 bit build.

Why does this calculation fail?

Jeff Cope
  • 781
  • 2
  • 7
  • 15
  • 2
    The calculation doesn't fail. Using doubles, rounding errors are to be expected. It is as correct as doubles allow it to be. – towr Mar 06 '14 at 20:22

2 Answers2

2

It doesn't fail -- you've just run into the limits of precision that are inherent in any representation of floating point arithmetic on a computer. For comparison, I just tried the same subtraction in an interactive Python shell:

>>> a = 1671.37
>>> b = 871.37
>>> a - b
799.9999999999999

The solution is to either accept the limits of floating point math, and round off your answers to a desired precision; or, switch to a different kind of numerical representation. For instance, since these values use two decimal places (dollars and cents?), you could multiply them by 100, and use integers (dividing by 100 only for display purposes, if and when necessary). Then there's binary-coded decimal, and arbitrary precision... I don't know offhand how you'd do those in Delphi, but they're probably overkill, depending on your application.

William McBrine
  • 2,166
  • 11
  • 7
  • `Currency` is much better in this case than `Integer` ;) – Sir Rufo Mar 06 '14 at 23:05
  • We were originally using currency which worked great for our needs but then started to create 64 bit compiles of our applications. That's when we discovered this error (something Embarcadero verified they would fix in XE6) with the currency that lead us to look at using doubles: http://stackoverflow.com/questions/21890858/why-is-64-bit-delphi-app-calculating-different-results-than-32-bit-build – Jeff Cope Mar 07 '14 at 13:32
1

Well I'm getting exactly the same result in Python ;)

Python 2.7.6 (default, Feb 24 2014, 16:00:34)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 1671.37
>>> b = 871.37
>>> c = 800.00
>>> t = a - c
>>> t = t - b
>>> print t
-1.13686837722e-13
>>>

Floating point arithmetic is not 100% precise (I just know it is complex to explain how a floating point number is represented inside the memory).

Please read this answer here:

https://stackoverflow.com/a/2080642/756056

Community
  • 1
  • 1
therealmarv
  • 3,692
  • 4
  • 24
  • 42