Link to home
Start Free TrialLog in
Avatar of gamesmeister
gamesmeisterFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Double maths

This one's got me tearing my hair out...

I have a set of classes that increment values, depending on a data type. A subset of one of those classes is below:

public class IncrementDoubleValue : IIncrementValue
{
      private double startValue;
      private double stepValue;
      private double maxValue;

      public object GetValue()
      {
            if (currentValue >= maxValue)
                  currentValue = startValue;
            else
                  currentValue += stepValue;

            return currentValue;
      }
}

The idea is simply to increment a double by the stepValue until it reaches the maxValue, at which point it starts again.

I was getting some strange results and started tracing this through. My values were as follows:

startValue: 1.0
stepValue: 0.001
maxValue: 999999999

Therefore I would expect to get: 1.0, 1.001, 1.002, 1.003, etc

However, instead I got:

1.0
1.001
1.0019999999999998
1.0029999999999997
1.0039999999999996
1.0049999999999994

Note how the last one also dropped by 2 in the final decimal place.

These are all exact values I've copied from the trace. Can anyone put me out of my misery and explain why this is happening?

Thanks
Gerry
Avatar of smegghead
smegghead
Flag of United Kingdom of Great Britain and Northern Ireland image

I've just tried this..

double start=1;
double increment=0.001;
for (int c1=0 ; c1<20 ; c1++)
{
      start+=increment;
      Console.WriteLine(start);
}

And it returned... which I would expect, are you sure there's nothing in there you're missing ?

1.001
1.002
1.003
1.004
1.005
1.006
1.007
1.008
1.009
1.01
1.011
1.012
1.013
1.014
1.015
1.016
1.017
1.018
1.019
1.02



ASKER CERTIFIED SOLUTION
Avatar of OfficeLineman
OfficeLineman

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I agree that double numbers aren't exact, and are inprecise by design, but I think that there is something else going on here, otherwise my example would have returned the same results as in the initial question.

Avatar of gamesmeister

ASKER

Honestly smegghead, I've checked it a dozen times, in debug mode, with those values in front of me. I hit F11 to step from "currentValue += stepValue" to "return currentValue", and those decimal places just appear from nowhere. There's no threading going on (and to be sure I've locked the method so it's not being updated externally) -  that's why I found it so baffling.

Office, that sounds pretty plausible. Is it a phenomenon particular to Doubles only, or do I have to worry about any other DataTypes (Singles spring to mind).

Many thanks for the responses
Gerry
Avatar of OfficeLineman
OfficeLineman

Hey smegghead, try your example up to 100.  Mine goes wonky right around c1 = 45:

double start=1;
double increment=0.001;
for (int c1=0 ; c1<100 ; c1++)
{
     start+=increment;
     Console.WriteLine(start);
}

[...]
1.04
1.041
1.042
1.043
1.044
1.045
1.04599999999999
1.04699999999999
1.04799999999999
1.04899999999999
1.04999999999999
1.05099999999999
[...]
This would be a problem for both floats and doubles, as they both follow the same specification.

The decimal type does not use the IEEE754 specification; it was designed to address the floating-point math issues inherent to floats and doubles, and provide a viable solution to monetary calculations that require more predictability than doubles.
Thanks for all the help guys