Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / July 2006

Tip: Looking for answers? Try searching our database.

Addition error in DotNet 2.0

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Owen - 14 Jul 2006 12:25 GMT
Hi all,
Wondering if someone can help me with this:

when i'm in Visual Studio 2005 I get a wierd addition error when adding
0.1+0.2 (both as doubles)

the result that comes back is  0.30000000000000004 not 0.3 as expected. Any
ideas what's causing this or what's wrong?

A few results:
0.1+0.2    0.30000000000000004    double
0.1+0.2+0.1+0.2    0.60000000000000009    double
0.1+0.3    0.4    double
0.2+0.3    0.5    double
Cowboy (Gregory A. Beamer) - MVP - 14 Jul 2006 13:44 GMT
Somewhere in your code, you are using floats, not doubles.

Try the following in a console app (C#):

static void Main(string[] args)
{
   double a = 0.1;
   double b = 0.2;
   double c = a + b;
   double d = 0.1 + 0.2;
   float e = 0.1f;
   float f = 0.2f;
   double g = e + f;
   
   
   Console.WriteLine("a={0}", a);
   Console.WriteLine("b={0}", b);
   Console.WriteLine("c={0}", c);
   Console.WriteLine("d={0}", d);
   Console.WriteLine("e={0}", e);
   Console.WriteLine("f={0}", f);
   Console.WriteLine("g={0}", g);
   Console.Read();
}

Signature

Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

***************************
Think Outside the Box!
***************************

> Hi all,
> Wondering if someone can help me with this:
[quoted text clipped - 10 lines]
> 0.1+0.3    0.4    double
> 0.2+0.3    0.5    double
Owen - 14 Jul 2006 14:03 GMT
Nope.
still not right. the console outputs correct but the underlying numbers are
wrong which fails the unit testing in my application.

Check out this screen shot:
http://www.bgeek.net/photos/d/3559-2/screen.jpg

Cheers
Owen Evans
Larry Lard - 14 Jul 2006 16:12 GMT
Cowboy - MVP (Gregory A. Beamer) wrote:
> Somewhere in your code, you are using floats, not doubles.

I think you'll find that the default formatting is leading you astray.

> Try the following in a console app (C#):
>
[quoted text clipped - 11 lines]
>     Console.WriteLine("b={0}", b);
>     Console.WriteLine("c={0}", c);

This prints 0.3, yes, but c is not 0.3. Try

    Console.WriteLine("c={0}", c-0.3);

>     Console.WriteLine("d={0}", d);

Doing the addition at compile time doesn't help, either, try

    Console.WriteLine("d={0}", d-0.3);

>     Console.WriteLine("e={0}", e);
>     Console.WriteLine("f={0}", f);
>     Console.WriteLine("g={0}", g);

It's only apparent in this example with float and not double because
double's default ToString rounds to a point which hides the
discrepancy, but float's doesn't (it has a bigger disrecpancy too).

>     Console.Read();
> }

In any event, more digits of precision would just be a palliative -
better to fix the real problem, and use an exact type (as I'm sure you
are aware).

--
Larry Lard
Replies to group please
When starting a new topic, please mention which version of VB/C# you
are using
Carl Daniel [VC++ MVP] - 14 Jul 2006 15:00 GMT
> Hi all,
> Wondering if someone can help me with this:
[quoted text clipped - 5 lines]
> the result that comes back is  0.30000000000000004 not 0.3 as
> expected. Any ideas what's causing this or what's wrong?

Your expectations are wrong.

The numbers 0.1 and 0.2 do not have exact representations in binary floating
point - which is what .NET uses for floats and doubles.  Consequently, when
you add a number very close to 0.1 to a number very close to 0.2, the best
you can hope for is a number very close to 0.3.  Four double, which you're
apparently using here, you can expect about 17 digits of accuracy.

When comparing floating point numbers for "equality", you should always
compare for equality wiithin some small range, e.g. instead of x == y, use
Math.Abs(x-y) < 0.0000000001.

When displaying floating point numbers, you should always specify how many
digits after the decimal point, according to your needs.

If you need to be able to add 0.1 to 0.2 and get exactly 0.3 (e.g. you're
doing financial calculations), then you should use the System.Decimal type
instead.  It is a decimal floating point number and can represent negative
powers of 10 (e.g. 0.1) exactly.  Be aware though - decimal is orders of
magnitude slower than double, so unless you really need absolute decimal
accuracy, you're probably better off using double.

You should also take a look at the paper at the following url.  It goes into
the details of working with binary floating point numbers in great detail.

http://docs.sun.com/source/806-3568/ncg_goldberg.html

-cd
Owen - 14 Jul 2006 15:10 GMT
Ok that explains why it's happening. but why is it different for 2003 and
2005? the unit tests used to pass in 2003, but now fail. And it's only for
these numbers ie if i change it to (double)0.1+(double)0.3 i get 0.4 and this
passes an nunit.Assert.AreEqual test.

Cheers
OWen Evans
Larry Lard - 14 Jul 2006 16:07 GMT
> Ok that explains why it's happening. but why is it different for 2003 and
> 2005? the unit tests used to pass in 2003, but now fail.

Well, when I ask the immediate window in VS2003 and VS2005

?0.1+0.2-0.3

both times it tells me

0.000000000000000055511151231257827.

I would be surprised if the details of the Framework's floating point
implementation had changed, but they would be perfectly within their
rights to do so, so long as they still met all the relevant contracts.

By the way, thanks for the example - I always used to use
0.1+0.1+0.1-0.3 evaluating to not zero as my 'pet teaching example' of
why not to use floating point types for exact calculations, but
0.1+0.2-0.3 not being zero is, I think, a little better.

Signature

Larry Lard
Replies to group please

Jon Skeet [C# MVP] - 16 Jul 2006 08:13 GMT
> Ok that explains why it's happening. but why is it different for 2003 and
> 2005? the unit tests used to pass in 2003, but now fail. And it's only for
> these numbers ie if i change it to (double)0.1+(double)0.3 i get 0.4 and this
> passes an nunit.Assert.AreEqual test.

You should always express this sort of test with a tolerance - i.e.
specify a range of values for which the test will pass. For more
information about floating point, along with a way of finding the exact
value of a floating point number (i.e. getting rid of formatting
rounding etc) see
http://www.pobox.com/~skeet/csharp/floatingpoint.html

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Carl Daniel [VC++ MVP] - 16 Jul 2006 15:14 GMT
> Ok that explains why it's happening. but why is it different for 2003
> and 2005? the unit tests used to pass in 2003, but now fail. And it's
> only for these numbers ie if i change it to (double)0.1+(double)0.3 i
> get 0.4 and this passes an nunit.Assert.AreEqual test.

The "why" is easy:  you were lucky (or perhaps it's unlucky).

-cd
Michael D. Ober - 17 Jul 2006 03:27 GMT
Has anyone actually tested Decimal vs. Double.  The reason I ask is that
both data types are implemented in the x87 FPU hardware (built into the
80486 and later) and have about the same clock cycle requirements.

Mike Ober.

> > Hi all,
> > Wondering if someone can help me with this:
[quoted text clipped - 34 lines]
>
> -cd
Carl Daniel [VC++ MVP] - 17 Jul 2006 04:37 GMT
> Has anyone actually tested Decimal vs. Double.  The reason I ask is
> that both data types are implemented in the x87 FPU hardware (built
> into the 80486 and later) and have about the same clock cycle
> requirements.

The decimal type is not implemented by the x87 FPU 0 or at least not
directly.

The .NET System.Decimal type is a wrapper around the OLE VAR_DECIMAL type
and is implemented by ole32.dll (IIRC).  Whether the decimal support library
makes use of the x87 decimal type I do not know.  If it does, it'd have to
be doing format conversion, because the x87 decimal stores the mantissa as
BCD (decimal digit per nibble), while the .NET decimal type stores the
mantissa as a 96-bit unsigned binary integer.  My guess would be that it
doesn't make use of the x87 decimal type at all.

-cd
Michael D. Ober - 17 Jul 2006 05:21 GMT
Thanks.

Mike.

> > Has anyone actually tested Decimal vs. Double.  The reason I ask is
> > that both data types are implemented in the x87 FPU hardware (built
[quoted text clipped - 13 lines]
>
> -cd
Norman Yuan - 14 Jul 2006 15:14 GMT
That is how "double" type works. See .NET framework document. It is the same
to other language where "duoble" or similar floating type is implemented. I
have been seeing the same or similar questions appearing in NGs for
classical VB every other week or so in many years.

If the rounding precision is an issue to your app, you might want to
consider to use "decimal" type instead of "double" or "single".

> Hi all,
> Wondering if someone can help me with this:
[quoted text clipped - 11 lines]
> 0.1+0.3 0.4 double
> 0.2+0.3 0.5 double

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.