3

When you have a IEEE754 compliant floating point implementation, then any comparisons with a NaN is false, even NaN == NaN, but +inf == +inf is true, why?

From my point of view, it would make more sense to say +inf == +inf is false, reasons:

  • The numbers of natural numbers and rational numbers, both are infinite but not the same.

  • If you have X=1e200 and Y=1e300 (both, X and Y are 64-bit doubles), so x==y is false, but x*1e200==y*1e200 is true true (both are +inf), which is mathematical incorrect.

  • There is already a special handling required, for NaN, where X==X is false, so there will not be much more implementation complexity to implement that +inf == +inf return false. Maybe even less, because inf and NaN us the same "exponent".

  • I do not see any advantage, or any application which require the fact that +inf == +inf. You should not compare any floating point values with == anyway.

  • X==Y is generel then true, if X-Y==0 is true, but inf-inf is NaN.

Edit

As nwellnhof allready wrote: The linked Question: C IEEE-Floats inf equal inf, is not the same, there was the question "why is the language implementation this way?", Here is the question "Why is the standard defined this way?". (And both questions are from the same user)

Community
  • 1
  • 1
  • 1
    Possible duplicate of [C IEEE-Floats inf equal inf](http://stackoverflow.com/questions/41834621/c-ieee-floats-inf-equal-inf) – phuclv Feb 02 '17 at 01:38
  • 1
    @LưuVĩnhPhúc As I noted in my answer to the linked question, I think this is not a duplicate. (*Why doesn't my code do what I expect* vs. *Why isn't the standard defined how I expect*.) – nwellnhof Feb 02 '17 at 01:41
  • In your first reason, you seem to be confusing cardinalities of infinite sets with points on the extended real line. Both happen to be called "infinity", but they really have nothing to do with each other. (And BTW, the cardinality of the set of natural numbers *is* the same as that of the set of rational numbers.) – Mark Dickinson Feb 03 '17 at 08:24

1 Answers1

5

You'd probably have to ask William Kahan, the primary architect behind IEEE 754-1985, but this answer sheds some light on the topic:

more importantly, there was no isnan( ) predicate at the time that NaN was formalized in the 8087 arithmetic; it was necessary to provide programmers with a convenient and efficient means of detecting NaN values that didn’t depend on programming languages providing something like isnan( ) which could take many years. I’ll quote Kahan’s own writing on the subject:

Were there no way to get rid of NaNs, they would be as useless as Indefinites on CRAYs; as soon as one were encountered, computation would be best stopped rather than continued for an indefinite time to an Indefinite conclusion. That is why some operations upon NaNs must deliver non-NaN results. Which operations? … The exceptions are C predicates “ x == x ” and “ x != x ”, which are respectively 1 and 0 for every infinite or finite number x [emphasis added] but reverse if x is Not a Number ( NaN ); these provide the only simple unexceptional distinction between NaNs and numbers [emphasis added] in languages that lack a word for NaN and a predicate IsNaN(x).

If +inf wasn't equal to +inf, the x != x test for NaNs wouldn't work because it would catch infinities as well. Back in 1985, a C programmer could have written:

#define is_nan(x)     ((x) != (x))
#define is_pos_inf(x) ((x) ==  1.0/0.0)
#define is_neg_inf(x) ((x) == -1.0/0.0)

With inf != inf, you'd need something like:

#define is_nan(x)     (!((x) >= 0) && !((x) <= 0))
#define is_pos_inf(x) ((x) != (x) && (x) > 0.0)
#define is_neg_inf(x) ((x) != (x) && (x) < 0.0)

I can see your point and I agree that having +inf != +inf is more correct from a purely mathematical standpoint. But IMO, it doesn't outweigh the practical considerations.

The [sets] of natural numbers and rational numbers, both are infinite but [have] not the same [cardinality].

This hasn't much to do with floating-point calculations.

If you have X=1e200 and Y=1e300 (both, X and Y are 64-bit doubles), so x==y is false, but x*1e200==y*1e200 is true true (both are +inf), which is mathematical incorrect.

Floating point math is inherently mathematically incorrect. You can find many finite floating-point numbers, X, Y, Z, with X != Y, where X <op> Z == Y <op> Z.

I do not see any advantage, or any application which require the fact that +inf == +inf. You should not compare any floating point values with == anyway.

I also can't see an application that would require +inf != +inf.

X==Y is [...] true, if X-Y==0 is true, but inf-inf is NaN.

This is in fact an inconsistency that +inf != +inf would solve. But it seems like a minor detail to me.

Community
  • 1
  • 1
nwellnhof
  • 32,319
  • 7
  • 89
  • 113
  • 1
    You cold still use `define is_nan(x) ( ((x)!=(x)) && !((x)<0) && !((x)>0) )`, (+inf would still be greater than 0 and -inf still be less than 0) even when `+inf != +inf` – 12431234123412341234123 Feb 02 '17 at 11:33
  • Or shorter: `define is_nan(x) ( !((x)<=0) && !((x)=>0) )` – 12431234123412341234123 Feb 02 '17 at 12:07
  • @12431234123412341234123 See my amended answer. – nwellnhof Feb 02 '17 at 17:07
  • 2
    This is the best one can do short of asking professor Kahan. Early drafts of the IEEE FP standard had provisions for a "projective mode" with regard to infinities which only had INF without a sign. In that mode comparisons between INF and finite numbers returned "unordered", but still INF compared equal to INF. There was a competing proposal to the KCS (Kahan-Coonen-Stone) proposal by Fraley & Walther of Hewlett-Packard that handled overflows differently, details *may* be in a document "Safe Treatment of Overflow and Underflow Conditions" which I can't find online, nor have a paper copy of. – njuffa Feb 02 '17 at 19:29
  • 3
    In some [early writing](http://www.dtic.mil/cgi-bin/GetTRDoc?AD=AD0769124), Kahan pointed out that there is no consistent way of dealing with infinities: some instances of INF are actually infinity (e.g. 1/0) while others are the result of overflow (as in the asker's example). I'd say this is the same issue that surrounds zeros: either a "clean" zero, or the result of underflow. The 10,000ft issue is that every floating-point number can represent a mathematical quantity exactly, or represent an interval, and generally we do not know which it is when performing a given floating-point operation. – njuffa Feb 02 '17 at 20:17