Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

float vs generic equality... #3241

Closed
vicuna opened this issue Mar 5, 2002 · 2 comments
Closed

float vs generic equality... #3241

vicuna opened this issue Mar 5, 2002 · 2 comments

Comments

@vicuna
Copy link

vicuna commented Mar 5, 2002

Original bug ID: 963
Reporter: administrator
Status: closed
Resolution: fixed
Priority: normal
Severity: feature
Category: ~DO NOT USE (was: OCaml general)

Bug description

Full_Name: Jacek Chrzaszcz
Version: 3.04&3.02
OS: Mandrake/Redhat Linux
Submission from: fw-gw-atm.mimuw.edu.pl (193.0.96.15)

Hello,

When I define

let eq = (=)

I understand that that results of (eq a b) and (a=b) may be different. But I
dont understand a few of them:

eq nan infinity;;

  • : bool = true (* !!?!?!? *)

nan=infinity;;

  • : bool = false

On the other hand:

eq 0. ~-.0.;;

  • : bool = true

0. = ~-.0.;;

  • : bool = true
    so positive and negative zero are identified even though they are printed
    diffrently and give different values in operations:

1./.0. = 1./. ~-.0.;;

  • : bool = false

eq (1./.0.) (1./. ~-.0.);;

  • : bool = false

The above, together with (eq nan infinity = true) and (eq nan neg_infinity =
true) make the generic equality non-transitive, which is a bit surprising...

Is this a bug or a feature ? I always thought that (eq) is something like "are
the representations of two things equal ?", but evidently it is more
complicated...

May-be the difference between (eq) and (=) for floats should be explained in the
manual... or a FAQ.

Jacek

@vicuna
Copy link
Author

vicuna commented Mar 7, 2002

Comment author: administrator

When I define

let eq = (=)

I understand that that results of (eq a b) and (a=b) may be different. But I
dont understand a few of them:

You've hit a delicate issue with generic equality (what you've defined
as eq).

When (=) is used with type float -> float -> bool, the compiler
specializes it to IEEE floating-point equality. I assume you are
familiar with IEEE equality; its noticeable features is that nan is
not equal to any float, including itself (which makes equality non
reflexive!).

However, generic equality (eq) is defined as x = y iff compare x y = 0,
and compare is a total ordering function, hence it doesn't know how to
"say" that x and y are not comparable, e.g. if x = nan. The somewhat
arbitrary behavior of compare in this case is to say that since
not (x < y) and not (x > y), then it must be the case that (x = y).
Hence:

eq nan infinity;;

  • : bool = true (* !!?!?!? *)

nan is not less than infinity, nor greater than infinity, so both are
equal :-(

nan=infinity;;

  • : bool = false

Here you get the correct IEEE behavior.

On the other hand:

eq 0. ~-.0.;;

  • : bool = true

0. = ~-.0.;;

  • : bool = true
    so positive and negative zero are identified even though they are printed
    diffrently and give different values in operations:

1./.0. = 1./. ~-.0.;;

  • : bool = false

eq (1./.0.) (1./. ~-.0.);;

  • : bool = false

This is normal according to IEEE equality semantics. Think of it in
terms of equality of limits: if you have a sequence of positive floats
(u_n) that converges to 0, and another sequence of negative floats
(v_n) that also converges to 0, both (u_n) and (v_n) have the same
limit; yet (1/u_n) and (1/v_n) have different limits, infinity and
neg_infinity.

The above, together with (eq nan infinity = true) and (eq nan neg_infinity =
true) make the generic equality non-transitive, which is a bit surprising...

Is this a bug or a feature ? I always thought that (eq) is something
like "are the representations of two things equal ?", but evidently
it is more complicated...

It is a bug, of the painful-to-fix kind :-) I know how to modify generic
comparison and equality to handle the case "not comparable", but at
significant cost. Namely, we can no longer assume that two physically
equal things (same pointers) are equal, since "nan <> nan" even if both
"nan" point to the same float heap block.

  • Xavier Leroy

@vicuna
Copy link
Author

vicuna commented Apr 18, 2004

Comment author: administrator

Since 2004/11, generic equality on floats behaves like IEEE equality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant