[comp.lang.c] ANSI really does want you to == float values.

rbutterworth@watmath.UUCP (04/13/87)

Since most people seem to be yelling into the wind and not
noticing what the others are saying, this is probably a bad
time to submit this, but anyway.

The ANSI standard defines functions such as strtod() that return
a double value, HUGE_VAL, upon failure.  That seems to imply that
the following pieces of code all should do the comparison the same
way.

    if (HUGE_VAL == strtod(args)) ...

    val = strtod(args);
    if (val == HUGE_VAL) ...

    bad = HUGE_VAL;
    val = strtod(args);
    if (val == bad) ...

Now does that mean that HUGE_VAL (and -HUGE_VAL) are defined so
that the comparisons will work correctly regardless of registers,
guard bits, optimization, etc.?  If so, do such numbers really
exist on all machines?
Probably not.  e.g. if "val" and "bad" above are registers with
extra guard bits that aren't automatically zeroed when the values
are loaded, they usually won't compare equal.

On the other hand if there isn't supposed to be anything special
about these numbers, does that mean that the compiler should
generate correct code for all doubles?  If so, is this even
possible on all machines?
Again, probably not.  At least not unless you are willing to put
up with some very inefficient code.  (e.g. whenever any two floating
values are compared they are first normalized and stored in temporary
memory somewhere.)

Or is the compiler itself supposed to know that HUGE_VAL is
special and generate "correct" comparison code for that case?

Or does any of this really matter?
Who bothers to check error status returns anyway?

gwyn@brl-smoke.UUCP (04/14/87)

In article <6909@watmath.UUCP> rbutterworth@watmath.UUCP (Ray Butterworth) writes:
>The ANSI standard defines functions such as strtod() that return
>a double value, HUGE_VAL, upon failure.  That seems to imply that
>the following pieces of code all should do the comparison the same
>way.

As you point out, the exact equality comparison may fail on some systems.
Therefore, you should not use it.  Most functions returning HUGE_VAL also
historically have some other error indicator as well.  I wish X3J11 had
adopted matherr(), which is a fairly good way to intercept such exceptions.

dave@sds.UUCP (04/15/87)

In article <6909@watmath.UUCP>, rbutterworth@watmath.UUCP (Ray Butterworth) writes:
> Now does that mean that HUGE_VAL (and -HUGE_VAL) are defined so
> that the comparisons will work correctly regardless of registers,
> guard bits, optimization, etc.?  [...]
> 
> On the other hand if there isn't supposed to be anything special
> about these numbers, does that mean that the compiler should
> generate correct code for all doubles?  [...]
> Again, probably not.  At least not unless you are willing to put
> up with some very inefficient code.  (e.g. whenever any two floating
> values are compared they are first normalized and stored in temporary
> memory somewhere.)

I would argue that unless instructed otherwise, the compiler should ALWAYS
produce code to normalize floating point numbers before comparisons.  Yes,
I know this grossly inefficient, but it is correct.  Consider:

#define PI	3.14159265
static double	sin_pi_4;
double		sin();

sin_pi_4 = sin(PI/4.0);
/* some code which doesn't change sin_pi_4	*/

if ( sin_pi_4 != sin(PI/4.0) )
	printf( "your compiler should be ashamed.\n" );


Since we can (hopefully :-) agree that sin(PI/4.0) is constant, the condition
in the if *must* be false; if it's not, I would say the compiler is producing
incorrect code.  Making the unwary programmer (and we all were at one time),
having to know & worry about 80-bit registers vs. 64 bit doubles, guard bits,
etc. is absurd.  Granted, Joe Number Cruncher Floating Point God may demand
that his program not normalize floating point numbers and perform all
[reasonable] optimizations; an appropriate compiler directive should be
available for experts of this type who need or want every bit of possible
speed at the expense of worrying about the floating point hardware.


Dave Schmidt

[ This space intentionally left blank. ]