By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,462 Members | 1,369 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,462 IT Pros & Developers. It's quick & easy.

Bug in Framework on Double arithmetic...?

P: n/a
Hi all,

I'm facing a strang issue doing calculation on Double values. I read
some thread on the newsgroups warning about type translations (eg
Single to Double), but here I'm doing no conversion at all.

The issue I'm facing looks so basic but I'm really lost... I'm doing
all my calculations in Double, and the results are not correct. Did I
miss something?

double a, b;
a = 4.5d;

b = a + 0.10d;
Console.WriteLine(ee == 4.6d); // returns true

b = a + 0.20d;
Console.WriteLine(ee == 4.7d); // returns true
b = a + 0.10d + 0.10d;
Console.WriteLine(ee == 4.7d); // returns false !!!
b = a + 0.30d;
Console.WriteLine(ee == 4.8d); // returns true
b = a + 0.10d + 0.10d + 0.10d;
Console.WriteLine(ee == 4.8d); // same: returns false
Many thanks in advance for your help,

Best regards,
Lionel

Aulofee supervision systems (http://www.aulofee.com)
* security and log correlation
* IT asset management and inventory
* reporting
* network cartography

May 16 '06 #1
Share this Question
Share on Google+
8 Replies


P: n/a

Lionel wrote:
Hi all,

I'm facing a strang issue doing calculation on Double values. I read
some thread on the newsgroups warning about type translations (eg
Single to Double), but here I'm doing no conversion at all.

The issue I'm facing looks so basic but I'm really lost... I'm doing
all my calculations in Double, and the results are not correct. Did I
miss something?

double a, b;
a = 4.5d;

b = a + 0.10d;
Console.WriteLine(ee == 4.6d); // returns true
Lucky.

b = a + 0.20d;
Console.WriteLine(ee == 4.7d); // returns true
Lucky again!
b = a + 0.10d + 0.10d;
Console.WriteLine(ee == 4.7d); // returns false !!!
Not surprising.


b = a + 0.30d;
Console.WriteLine(ee == 4.8d); // returns true
b = a + 0.10d + 0.10d + 0.10d;
Console.WriteLine(ee == 4.8d); // same: returns false
Many thanks in advance for your help,


Short answer: Don't use floating point types for exact calculation. In
particular, don't ever use == with floating point types.

Slightly longer answer: If you are using quantities best represented by
floating point types (and numbers such as 0.1, 4.6, are not), and you
want to compare equality, decide on some small epsilon which for your
application can mean 'close enough'; and then say two floating point
quantites are equal if they are within epsilon of each other. eg:

static const double epsilon = 0.0001d;
static bool CloseEnough(double d1, double d2)
{
return (Math.Abs(d1 - d2) < epsilon);
}
Here's the C# for my favorite example for why floating point is
inappropriate for exact quantities:

Console.WriteLine((0.1d + 0.1d + 0.1d - 0.3d));

Try it! (First guess what you think the output will be of course...)

Long answer: Go look up floating point at wikipedia or somewhere :)

--
Larry Lard
Replies to group please

May 16 '06 #2

P: n/a
This is no bug. You can never assume that for example 2.0 + 0.1 == 2.1.
floating point numbers are using an approximating internal representation
thus you can never rely on exact values but just approximated ones.

--
"Lionel" <ec*************@gmail.com> schrieb im Newsbeitrag
news:11*********************@j55g2000cwa.googlegro ups.com...
Hi all,

I'm facing a strang issue doing calculation on Double values. I read
some thread on the newsgroups warning about type translations (eg
Single to Double), but here I'm doing no conversion at all.

The issue I'm facing looks so basic but I'm really lost... I'm doing
all my calculations in Double, and the results are not correct. Did I
miss something?

double a, b;
a = 4.5d;

b = a + 0.10d;
Console.WriteLine(ee == 4.6d); // returns true

b = a + 0.20d;
Console.WriteLine(ee == 4.7d); // returns true
b = a + 0.10d + 0.10d;
Console.WriteLine(ee == 4.7d); // returns false !!!
b = a + 0.30d;
Console.WriteLine(ee == 4.8d); // returns true
b = a + 0.10d + 0.10d + 0.10d;
Console.WriteLine(ee == 4.8d); // same: returns false
Many thanks in advance for your help,

Best regards,
Lionel

Aulofee supervision systems (http://www.aulofee.com)
* security and log correlation
* IT asset management and inventory
* reporting
* network cartography

May 16 '06 #3

P: n/a
Larry Lard <la*******@hotmail.com> wrote:

<snip>
Here's the C# for my favorite example for why floating point is
inappropriate for exact quantities:

Console.WriteLine((0.1d + 0.1d + 0.1d - 0.3d));

Try it! (First guess what you think the output will be of course...)


Hmm... despite understanding floating point reasonably well, I'd
expected that to be 0. No calculations are done in the above code at
runtime - it's all done by the compiler. I'd expect the compiler to be
smart enough to sort out constant expressions somewhat better. I must
look at what the language spec says...

--
Jon Skeet - <sk***@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
May 16 '06 #4

P: n/a
> Larry Lard <la*******@hotmail.com> wrote:

<snip>
Here's the C# for my favorite example for why floating point is
inappropriate for exact quantities:

Console.WriteLine((0.1d + 0.1d + 0.1d - 0.3d));

Try it! (First guess what you think the output will be of course...)


Hmm... despite understanding floating point reasonably well, I'd
expected that to be 0. No calculations are done in the above code at
runtime - it's all done by the compiler. I'd expect the compiler to be
smart enough to sort out constant expressions somewhat better. I must
look at what the language spec says...


Wouldn't the compiler just perform that same calculation internally,
using the exact same "roundoffs", and so ending up with the same
result as the resulting program would get it *that* performed the
calculation?

A quick test:
Console.WriteLine((0.1d + 0.1d + 0.1d - 0.3d));
double d1 = 0.1d;
double d2 = 0.3d;
Console.WriteLine((d1 + d1 + d1 - d2));
resulted in twice 5,55111512312578E-17

Hans Kesting
May 16 '06 #5

P: n/a
Hans Kesting <ne***********@spamgourmet.com> wrote:
Hmm... despite understanding floating point reasonably well, I'd
expected that to be 0. No calculations are done in the above code at
runtime - it's all done by the compiler. I'd expect the compiler to be
smart enough to sort out constant expressions somewhat better. I must
look at what the language spec says...


Wouldn't the compiler just perform that same calculation internally,
using the exact same "roundoffs", and so ending up with the same
result as the resulting program would get it *that* performed the
calculation?


Not necessarily. It appears to in this case, but I wouldn't have been
surprised to find that the compiler could work to a higher precision
(or use decimal arithmetic) in order to evaluate constant expressions.

You piqued my curiosity though, so I've checked with the spec, and
indeed:

<quote>
The compile-time evaluation of constant expressions uses the same rules
as run-time evaluation of non-constant expressions, except that where
run-time evaluation would have thrown an exception, compile-time
evaluation causes a compile-time error to occur.
</quote>

That seems to be a reasonable description of the observed behaviour.

--
Jon Skeet - <sk***@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
May 16 '06 #6

P: n/a
Jon Skeet [C# MVP] <sk***@pobox.com> checked with the spec:

<quote>
The compile-time evaluation of constant expressions uses the same rules
as run-time evaluation of non-constant expressions, except that where
run-time evaluation would have thrown an exception, compile-time
evaluation causes a compile-time error to occur.
</quote>

That seems to be a reasonable description of the observed behaviour.


IMO a very reasonable behavior. Compile-time evaluation should
be transparent. I'd hate to see the behavior of my program change
just because I changed a constant to a parameter with the same value.

Ole N.
May 16 '06 #7

P: n/a
Ole Nielsby <ol*********@snailmail.dk> wrote:
That seems to be a reasonable description of the observed behaviour.


IMO a very reasonable behavior. Compile-time evaluation should
be transparent. I'd hate to see the behavior of my program change
just because I changed a constant to a parameter with the same value.


Well, there can be changes in terms of string handling, certainly. For
instance:

string x = "hello Jon";
string y = "hello "+"Jon";
string name = "Jon";
string z = "hello "+name;

x and y are guaranteed to be references to the same object. z is
guaranteed to be different.

--
Jon Skeet - <sk***@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
May 16 '06 #8

P: n/a
This is not a .NET thing. This is universal across all languages (that
I've ever worked in) and all chipsets (that I've ever worked on).

Floating point numbers cannot be represented exactly. They are all very
accurate approximations. So, as you do arithmetic with them... even
apparently simple arithmetic, you introduce small amounts of error.

There is an entire area of computing, called Numerical Analysis, that
studies how various algorithms affect floating point error (either
accentuating it or damping it). However, at the very least, you can
never count on two floating point quantities that "should be" equal
being in fact equal. As Larry pointed out, if you want to compare
floating point quantities for "equality" you must choose a minimum
tolerance for error (aka an "epsilon") and compare using that.

This is, incidentally, why you should never use floating point (ie
float or double) to represent monetary values. You should always use
the Decimal type. I believe that Decimal is considerably less efficient
than float or double (I could be wrong), but it does make stronger
guarantees about accuracy.

double and float are generally used for mathematical calculations such
as work in engineering or the sciences, statistical analysis, etc.

decimal is more generally used in business, where you can't just "lose
a penny" here and there and get away with it.

May 16 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.