473,381 Members | 1,425 Online

# double type problem

Hi,

I have a strange problem about a simple sum operation on a double variable.
There is a loop in my application like this :

double _max = 0.4;
double _step = 0.1;

for (double d = 0.0; i < _max || double_equal (i, _max); i += step)
{
// Do something...
}

double_equal() is an epsilon based equality test function.

The problem is i's value on 4. turn. When I watch I see 0.30000000000000004
insted of 0.3
This is problematic because I compare it some other doubles in the loop but
even epsilon based approximitation will fail in this case.

It is interesting that this only appears on loop's 4. turn. On 5.turn the
value is 0.4, excellent!

What is the reason and how can I overcome this?

Aug 14 '08 #1
7 1563
Kürşat <ku***********@gmail.comwrote:
I have a strange problem about a simple sum operation on a double variable.
There is a loop in my application like this :

double _max = 0.4;
double _step = 0.1;

for (double d = 0.0; i < _max || double_equal (i, _max); i += step)
{
// Do something...
}

double_equal() is an epsilon based equality test function.

The problem is i's value on 4. turn. When I watch I see 0.30000000000000004
insted of 0.3
This is problematic because I compare it some other doubles in the loop but
even epsilon based approximitation will fail in this case.
Sounds like your epsilon is too small then.
It is interesting that this only appears on loop's 4. turn. On 5.turn the
value is 0.4, excellent!

What is the reason and how can I overcome this?
See http://pobox.com/~skeet/csharp/floatingpoint.html and
http://pobox.com/~skeet/csharp/decimal.html

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 14 '08 #2
I used the Epsilon provided by the double class and expected deviations
related to the double arithmetics will fall the range that this provided
epsilon determines.

It seems I should determine an appropriate epsilon value instead of relying
on the provided epsilon.

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
Kürşat <ku***********@gmail.comwrote:
I have a strange problem about a simple sum operation on a double
variable.
There is a loop in my application like this :

double _max = 0.4;
double _step = 0.1;

for (double d = 0.0; i < _max || double_equal (i, _max); i += step)
{
// Do something...
}

double_equal() is an epsilon based equality test function.

The problem is i's value on 4. turn. When I watch I see
0.30000000000000004
insted of 0.3
This is problematic because I compare it some other doubles in the loop
but
even epsilon based approximitation will fail in this case.
Sounds like your epsilon is too small then.
It is interesting that this only appears on loop's 4. turn. On 5.turn the
value is 0.4, excellent!

What is the reason and how can I overcome this?
See http://pobox.com/~skeet/csharp/floatingpoint.html and
http://pobox.com/~skeet/csharp/decimal.html

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 14 '08 #3
Kürsat <ku***********@gmail.comwrote:
I used the Epsilon provided by the double class and expected deviations
related to the double arithmetics will fall the range that this provided
epsilon determines.

It seems I should determine an appropriate epsilon value instead of relying
on the provided epsilon.
Yes. If you look at the documentation for double.Epsilon you'll see why
it's really not suitable for this kind of use.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 14 '08 #4
On Aug 14, 2:44*pm, "Kürsat" <kursatthek...@gmail.comwrote:
I used the Epsilon provided by the double class and expected deviations
related to the double arithmetics will fall the range that this provided
epsilon determines.
MSDN has this to say on Double.Epsilon:

"If you create a custom algorithm that determines whether two floating-
point numbers can be considered equal, you must use a value that is
greater than the Epsilon constant to establish the acceptable absolute
margin of difference for the two values to be considered equal.
(Typically, that margin of difference is many times greater than
Epsilon.)"

I don't see why you don't just use <= in your specific case here,
since the number will fall in the range you require... but if you
really need it, you'd probably want to just use decimal (it has
similar issues as well, but they're more predictable because it's
decimal and not binary - so you can be sure that any decimal number is
represented exactly as you wrote it).
Aug 14 '08 #5
To see why the "<=" operator would not be appropriate let's look at an
example:

I want to add numbers between 0.0-0.3 stepping 0.1 (0.0, 0.1, 0.2, 0.3) to a
listbox:

double _start = 0.0;
double _end = 0.3;
double _step = 0.1;

for (double d = _start; d <= _end; d+=_step)
{
}

This adds "0.0", "0.1" and "0.2" to the ListBox but not "0.3" bacause on 4.
turn, d contains the value 0.30000000000000004 which is neither less than
nor equal to 0.3.
"Pavel Minaev" <in****@gmail.comwrote in message
On Aug 14, 2:44 pm, "Kürsat" <kursatthek...@gmail.comwrote:
I used the Epsilon provided by the double class and expected deviations
related to the double arithmetics will fall the range that this provided
epsilon determines.
MSDN has this to say on Double.Epsilon:

"If you create a custom algorithm that determines whether two floating-
point numbers can be considered equal, you must use a value that is
greater than the Epsilon constant to establish the acceptable absolute
margin of difference for the two values to be considered equal.
(Typically, that margin of difference is many times greater than
Epsilon.)"

I don't see why you don't just use <= in your specific case here,
since the number will fall in the range you require... but if you
really need it, you'd probably want to just use decimal (it has
similar issues as well, but they're more predictable because it's
decimal and not binary - so you can be sure that any decimal number is
represented exactly as you wrote it).
Aug 14 '08 #6
Kürsat wrote:
I used the Epsilon provided by the double class and expected deviations
related to the double arithmetics will fall the range that this provided
epsilon determines.

It seems I should determine an appropriate epsilon value instead of relying
on the provided epsilon.
The provided epsilon value would work if the difference would come from
a single calculation. The difference grows for each iteration, so you
need a larger epsilon value the more iterations you have.

Use an integer for the loop, and calculate the double value from that in
each iteration. That way you don't have any problems with the loop, and
you don't have any accumulative error in the value:

for (int i = 0; i < 4; i++) {
double d = (double)i * 0.1;
// do something...
}

--
_____
http://www.guffa.com
Aug 14 '08 #7
Kürsat wrote:
>I used the Epsilon provided by the double class and expected
deviations related to the double arithmetics will fall the range that
this provided epsilon determines.

It seems I should determine an appropriate epsilon value instead of
relying on the provided epsilon.

The provided epsilon value would work if the difference would come from
a single calculation.
No.

Double.Epsilon is not related to the uncertainty of a number x.

It is the smallest number 0.

It is not (even though the name somehow gives the association)
the well known eps (smallest number where x + eps = x).

System.Double.Epsilon is 4.94065645841247e-324

machar eps is 2.22044605E-016

(and even if it were eps, then the uncertainty would not
be eps even on a single calculation)

Arne
Aug 15 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.