Double comparison problem

M

Mr Doppino

Hi people,
I would like to submit a problem about double comparison. Here's the code:

struct Cross_point {
int cross_id;
int x, y;
int street_oriz, street_vert;
};

--------------------------------
double nodex, nodey;
Cross_point reference_cross;

***
// Here there are assignments to nodex, nodey, and reference_cross
***

if (nodex == ((double)reference_cross.x))
move_dir = 1;
else if (nodey == ((double)reference_cross.y))
move_dir = 2;
else
fprintf(stderr,"[%f|%f] - cross(%f|%f)\n",nodex, nodey,
double(reference_cross.x), double(reference_cross.y));
-------------------------

The problem is that sometimes even though the values of nodex and
reference_cross.x OR nodey and reference_cross.y are the same I get the
error message. The printing show the values are equal.

Here's the output i get:

[527.000000|601.232221] - cross(527.000000|627.000000)
[527.000000|625.344833] - cross(527.000000|627.000000)
[527.000000|605.427903] - cross(527.000000|627.000000)
[632.289882|627.000000] - cross(622.000000|627.000000)
[639.335527|627.000000] - cross(622.000000|627.000000)
[650.641926|627.000000] - cross(660.000000|627.000000)
[658.736125|627.000000] - cross(660.000000|627.000000)

Thank you

Frank
 
D

Dietmar Kuehl

Mr said:
The problem is that sometimes even though the values of nodex and
reference_cross.x OR nodey and reference_cross.y are the same I get the
error message. The printing show the values are equal.

Do you, now? Maybe that is because you failed to investigate what
floating point is all about and failed to realize that floating
point values typically do not compare equal even though they
should contain the same value. Thus, to detect whether floating
point values are equal, you would use some form of epsilon.

The fact that "printing show the values are equal" is due to
tricky rounding in printing routines to get "expected" values
in typical cases. For example, users want to see "0.1" even
though this value cannot be represented exactly using a floating
point with a base of 2.
 
K

Karl Heinz Buchegger

Dietmar said:
The fact that "printing show the values are equal" is due to
tricky rounding in printing routines to get "expected" values
in typical cases. For example, users want to see "0.1" even
though this value cannot be represented exactly using a floating
point with a base of 2.

That's all right, but doesn't explain what the OP is seeing.
601.233331 and 627.00 are far to different that this explanation
applies.

Having said that: I have no explanation for that behaviour.
 
K

Karl Heinz Buchegger

Karl said:
That's all right, but doesn't explain what the OP is seeing.
601.233331 and 627.00 are far to different that this explanation
applies.

Having said that: I have no explanation for that behaviour.

Appologies. You are quite right. I misread the OP's post.
The difference in the y component isn't the problem. The
problem is in the x component which should be equal but
aren't because of floating point problems.
Exactly what you describe.
 
C

chris

Mr said:
Hi people,
I would like to submit a problem about double comparison. Here's the
code:

struct Cross_point {
int cross_id;
int x, y;
int street_oriz, street_vert;
};

--------------------------------
double nodex, nodey;
Cross_point reference_cross;

***
// Here there are assignments to nodex, nodey, and reference_cross
***

if (nodex == ((double)reference_cross.x))

There are two groups of people in this world.

1) Those who don't fully understand all of the details about performing
== and != on floating points values. They should never use == or != on
floating point values (not being mean or anything, they just shouldn't).

2) Those who do understand all the details about performing == and != on
floating point values. They don't use == and !=, so don't have to be
told not to :)

Chris
 
J

John Cochran

Hi people,
I would like to submit a problem about double comparison. Here's the code:

struct Cross_point {
int cross_id;
int x, y;
int street_oriz, street_vert;
};

--------------------------------
double nodex, nodey;
Cross_point reference_cross;

***
// Here there are assignments to nodex, nodey, and reference_cross
***

if (nodex == ((double)reference_cross.x))
move_dir = 1;
else if (nodey == ((double)reference_cross.y))
move_dir = 2;
else
fprintf(stderr,"[%f|%f] - cross(%f|%f)\n",nodex, nodey,
double(reference_cross.x), double(reference_cross.y));
-------------------------

The problem is that sometimes even though the values of nodex and
reference_cross.x OR nodey and reference_cross.y are the same I get the
error message. The printing show the values are equal.

Here's the output i get:

[527.000000|601.232221] - cross(527.000000|627.000000)
[527.000000|625.344833] - cross(527.000000|627.000000)
[527.000000|605.427903] - cross(527.000000|627.000000)
[632.289882|627.000000] - cross(622.000000|627.000000)
[639.335527|627.000000] - cross(622.000000|627.000000)
[650.641926|627.000000] - cross(660.000000|627.000000)
[658.736125|627.000000] - cross(660.000000|627.000000)

Thank you

Frank

Sorry, but they're not equal. In fact in any program where floating point
numbers are used attempting to compare for equality *or* inequality is
usually a mistake. Replace your line:

fprintf(stderr,"[%f|%f] - cross(%f|%f)\n",nodex, nodey,
double(reference_cross.x), double(reference_cross.y));

with:

fprintf(stderr,"[%f|%f] - cross(%f|%f) - diff(%e|%e)\n",nodex, nodey,
double(reference_cross.x), double(reference_cross.y),
nodex - double(reference_cross.x),
nodey - double(reference_cross.y));

to see what's going on.

Hope this helps,
John Cochran
 
D

Dietmar Kuehl

chris said:
There are two groups of people in this world.

1) Those who don't fully understand all of the details about performing
== and != on floating points values. They should never use == or != on
floating point values (not being mean or anything, they just shouldn't).

2) Those who do understand all the details about performing == and != on
floating point values. They don't use == and !=, so don't have to be
told not to :)

I'd say you fall into the first group! After all, comparing floating
point values representing reasonably sized integers is perfectly
valid even using '==' or '!=': you can use floating point values as a
form of bigger integer. You just have to take care of the values
staying in a certain range. Actually, you can also do exact
computations
for other values, i.e. those which can represented exactly. The only
thing to note is that the set of useful values is not closed over the
operations and you need to realize when the result of the operation is
of different kind (e.g. when addition or multiplication overflows,
substraction cancels leading bits, and division is only valid for
certain value). Sure enough, for most of my uses I don't play tricks
with floating point values but it is still possible and if you e.g.
need a 64 bit integer on a platform not supporting some form of
"long long" it can be an appropriate choice to use a 'long double'.
 
C

chris

Dietmar said:
I'd say you fall into the first group! After all, comparing floating
point values representing reasonably sized integers is perfectly
valid even using '==' or '!=': you can use floating point values as a
form of bigger integer. You just have to take care of the values
staying in a certain range. Actually, you can also do exact
computations
for other values, i.e. those which can represented exactly. The only
thing to note is that the set of useful values is not closed over the
operations and you need to realize when the result of the operation is
of different kind (e.g. when addition or multiplication overflows,
substraction cancels leading bits, and division is only valid for
certain value). Sure enough, for most of my uses I don't play tricks
with floating point values but it is still possible and if you e.g.
need a 64 bit integer on a platform not supporting some form of
"long long" it can be an appropriate choice to use a 'long double'.
OK, I apologise, I was perhaps a little too strong :) There are cases
where == and != can be used safely as long as you stay within some
reasonably tight bounds, as long as are careful :) But like you say you
have to be careful, so I find it easier to scare people off using == and
!= altogether, because I've seen far, far more cases where they were
being used incorrectly, and only a handful where they were being used
correctly, and in those cases the people using them knew they were using
them correctly :)

The idea of using a long double to replace a long long wasn't one I'd
seen before, thats quite a neat idea (although once again requires being
reasonably careful).

Chris
 
H

Howard

chris said:
There are two groups of people in this world.

Actually, there are THREE groups of people in this world:

1) those who can count, and

2) those who can't

:)
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Howard said:
Actually, there are THREE groups of people in this world:

There are 10 goups:

- People that knows the binary system.

- Other people.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,197
Messages
2,571,040
Members
47,642
Latest member
arunkumar99

Latest Threads

Top