473,405 Members | 2,379 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

Bug in Framework on Double arithmetic...?

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
8 2589

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
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
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
> 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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
by: David | last post by:
hello. when doing the simple following computation, the value put into the variable numMinusOne is NOT the same as what the computation is showed to be in the Watch window!! here is the code:...
33
by: Daniel Fadlun | last post by:
Is there a bigger, mathematical, data type in C than the double (64 bit) one or the old long double (80 bit)? I'd like to add precision to my mathematical application, but I can't figure out how....
11
by: Greenhorn | last post by:
Hi, K&R says that "floating point constants contain a decimal point (123.4) or an exponent (1e-2) or both; their type is double; unless suffixed. The suffixes f or F indicate a float constant; l...
17
by: Andreas Huber | last post by:
What follows is a discussion of my experience with .NET generics & the ..NET framework (as implemented in the Visual Studio 2005 Beta 1), which leads to questions as to why certain things are the...
60
by: Erick-> | last post by:
hi all... I've readed some lines about the difference between float and double data types... but, in the real world, which is the best? when should we use float or double?? thanks Erick
116
by: Dilip | last post by:
Recently in our code, I ran into a situation where were stuffing a float inside a double. The precision was extended automatically because of that. To make a long story short, this caused...
9
by: Tobias | last post by:
Let: double x,y; double z = max(x,y); Does the standard ensure that ( z == 0.0 ) || ( x/z == 1.0 ) || ( y/z == 1.0 ) always gives true?
206
by: md | last post by:
Hi Does any body know, how to round a double value with a specific number of digits after the decimal points? A function like this: RoundMyDouble (double &value, short numberOfPrecisions) ...
2
by: Markus Dehmann | last post by:
I have two integers i1 and i2, the second of which is guaranteed to be between 0 and 99, and I encode them into one double: double encoded = (double)i1 + (double)i2 / (double)100; So, for...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.