?
Solved

Double maths

Posted on 2006-05-03
7
Medium Priority
?
270 Views
Last Modified: 2010-04-16
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
0
Comment
Question by:gamesmeister
  • 3
  • 2
  • 2
7 Comments
 
LVL 10

Expert Comment

by:smegghead
ID: 16601290
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
 
LVL 2

Accepted Solution

by:
OfficeLineman earned 2000 total points
ID: 16601485
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
 
LVL 10

Expert Comment

by:smegghead
ID: 16601501
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 4

Author Comment

by:gamesmeister
ID: 16601580
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
 
LVL 2

Expert Comment

by:OfficeLineman
ID: 16601687
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
 
LVL 2

Expert Comment

by:OfficeLineman
ID: 16601711
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
 
LVL 4

Author Comment

by:gamesmeister
ID: 16603396
Thanks for all the help guys
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…
Suggested Courses
Course of the Month14 days, 5 hours left to enroll

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question