[comp.unix.aux] Bug?

steveg@tove.umd.edu (Steve Green) (09/27/89)

Why does this program print "no" under AUX and print "yes" on this vax?

main ()
{
	double x = .5;

	if (.4 <= x - .1)
		printf ("Yes\n");
	else
		printf ("No\n");
}

What am I missing?  Is it time for me to re-read my K&R??
Is it just my AUX that is doing it?  System V?
--
	-steveg@tove.umd.edu		..uunet!tove.umd.edu!steveg
"Ignore the message: 'ld warning: file /tmp/kernAAAa06386 has no relocation
information' if it appears."

earleh@eleazar.dartmouth.edu (Earle R. Horton) (09/28/89)

In article <19831@mimsy.UUCP> steveg@tove.umd.edu (Steve Green) writes:
>
>Why does this program print "no" under AUX and print "yes" on this vax?
>
>main ()
>{
>	double x = .5;
>
>	if (.4 <= x - .1)
>		printf ("Yes\n");
>	else
>		printf ("No\n");
>}
>
>What am I missing?  Is it time for me to re-read my K&R??
>Is it just my AUX that is doing it?  System V?

A/UX gives the seemingly false result because the temporary used to
hold "x - .1" is a 68881 register.  These registers hold two bytes
more of information than a double.  The temporary is not rounded after
the computation of "x - .1," and so the equality test fails.  If you
trace through this code using sdb to single-step machine instructions,
you will see what is happening here.

I don't think K&R says anything about this, because K&R assumes that
"double" is the natural size for a floating point quantity in the
local implementation.  In this case, that is false.  The natural size
is mc68881 96-bit extended.  Note that floating point constants are
stored in 64 bits, not 96.

It is in general bad practice to apply an equality test to the result
of a computation.  Instead of
	( a == b )
use
	( ( a < b + MINDOUBLE ) && ( a > b - MINDOUBLE ) )

MINDOUBLE is in <values.h>.

Furthermore, if the computation is very involved, then the machine
result may diverge from the ideal result by more than this.  All the
gory details may be found in any good textbook on numerical methods.

Earle R. Horton

brent@capmkt.COM (Brent Chapman) (09/29/89)

earleh@eleazar.dartmouth.edu (Earle R. Horton) writes:

# It is in general bad practice to apply an equality test to the result
# of a computation.  Instead of
# 	( a == b )
# use
# 	( ( a < b + MINDOUBLE ) && ( a > b - MINDOUBLE ) )
# 
# MINDOUBLE is in <values.h>.

Yeah, _right_.  Nice, clear, concise code there.  Why shouldn't I reasonably
expect the compiler to do this for me?


-Brent
--
Brent Chapman                                   Capital Market Technology, Inc.
Computer Operations Manager                     1995 University Ave., Suite 390
brent@capmkt.com                                Berkeley, CA  94704
{apple,lll-tis,uunet}!capmkt!brent              Phone:  415/540-6400

coolidge@brutus.cs.uiuc.edu (John Coolidge) (09/29/89)

brent@capmkt.COM (Brent Chapman) writes:
>earleh@eleazar.dartmouth.edu (Earle R. Horton) writes:
># It is in general bad practice to apply an equality test to the result
># of a computation.  Instead of
># 	( a == b )
># use
># 	( ( a < b + MINDOUBLE ) && ( a > b - MINDOUBLE ) )
># 
># MINDOUBLE is in <values.h>.
>Yeah, _right_.  Nice, clear, concise code there.  Why shouldn't I reasonably
>expect the compiler to do this for me?

Because it can produce very non-intuitive results. For instance, if the
compiler were to do it automatically it's entirely possible that
	if( ( a == b ) && ( b == c ) && (a != c) ) 
		printf( "What happened?\n" );
would print "What happened?" a lot. The reason is that a could well
equal b within the fuzz factor, and b could equal c, but a could be
2*MINDOUBLE away from c's value and hence not be equal.

That's why compilers don't automatically generate code to 'fix' problems
like this: because it might cause far bigger problems for people
doing lots of floating point ops. In general floating point is a
big problem --- equality tests on floating point numbers are a bad
idea in most languages. Also, things like a*(b+c) often don't equal
a*b+a*c, a*(b*c) is often unequal to (a*b)*c, and so on.

Followups to comp.lang.c, because this is more a C language issue.
It's certainly not specific to A/UX anymore.

--John

--------------------------------------------------------------------------
John L. Coolidge     Internet:coolidge@cs.uiuc.edu   UUCP:uiucdcs!coolidge
Of course I don't speak for the U of I (or anyone else except myself)
Copyright 1989 John L. Coolidge. Copying allowed if (and only if) attributed.
You may redistribute this article if and only if your recipients may as well.