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
LVL 4
gamesmeisterAsked:
Who is Participating?
 
OfficeLinemanConnect With a Mentor Commented:
That's happening because of the IEEE754 specification for floating point numbers.  As far as your computer is concerned, there is no such number as 0.001.  There's a number that's very very close, represented by a series of 1s and 0s that approximate it.  This causes doubles to be imprecise in many cases.

You should consider using the Decimal class for better precision, or round the numbers off to an appropriate number of decimal places before comparison.
0
 
smeggheadCommented:
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



0
 
smeggheadCommented:
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.

0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
gamesmeisterAuthor Commented:
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
0
 
OfficeLinemanCommented:
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
[...]
0
 
OfficeLinemanCommented:
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.
0
 
gamesmeisterAuthor Commented:
Thanks for all the help guys
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.