Schauble@mit-multics.arpa (03/12/87)
Branner at TCGOULD.TN.CORNELL.EDU writes In many numerical programs you do not want to repeat some calculation if some floating-point variable has not changed. Therefore, double x,y; x = y; ... if (x==y) ... SHOULD be available (and work correctly) even in implementations where (x*y == y*x) fails. And it should be no problem to implement, since x and y are two copies of the same number in the same internal format. (This is very different from the common mistake of expecting infinite precision when using FP variables in loop termination criteria...) - Moshe Braner 2-------------------- It's rare that the two numbers are just exact copies of the same variable. Usually one goes through slightly different calculation paths. Also, as an extreme case, I know of one compiler where x=y if(x==y) would fail because the x=y did rounding. None of this mentions the countless times I've seen people using equal to end loops, mathematical types who were surprised that sin(PI) != 1.0, annd so on. I'll stand by my original comment. Test for equality on floating point numbers is machine and compiler dependant. the only question is do we tell people about this. For your example, you should have written if (fabs(x-y) < EPSILON) Paul Schauble at MIT-Multics.edu
ger@qtecmuc.UUCP (03/16/87)
I had a similar problem today, with Microsoft C 4.0 on an IBM-AT compatible. The two programs #include <math.h> double a=0.01, b=0.01; int c; main() { a=floor(1.e5*a/0.5)/1.e5; if(a!=b) printf("not equal"); else printf("equal"); } /****/ and /****/ /* declarations as above ... */ main() { a=floor(1.e5*a+.5)/1.e5; c=1; /* This is the only difference */ if(a!=b) printf("not equal"); else printf("equal"); } /*****/ yielded different results. the first one says: 'Not equal', while the other one prints out 'equal'. With a debugger I found the reason for this strange behaviour: The compiler tries to hold the result of the floor... statement in the 80 bit register of the 8087 or the emulator and loads just b into another register for the comparison, if there is no other statement inbetween. Thus the compiler compares the 80-bit value resulting from previous operations and b, which is extended from 64 bit double precision to the internal 80 bit format, giving a!=b. If there is another statement like 'c=1' or anything else between the evaluation of floor .... and the comparison, the result of floor... is written to the variable 'a' correctly in 64 bit format, then loaded and extended again to 80 bit format, which results in a==b. My question: is this behaviour legal C ???? I always thought, double variables could only be compared with double precision, not with the precision of some internal format, depending of other statements, like 'c=1'. Too much optimization in my eyes. Gerhard Pehland Quantec Tonstudiotechnik, Munich W-Germany UUCP: ....!mcvax!unido!qtecmuc!ger Sorry for my english...
brianc@hpvcla.HP.COM (Brian Cripe) (03/17/87)
> For your example, you should have written > if (fabs(x-y) < EPSILON) Actually, I think the following is better: #define FLOAT_EQUAL(a, b) (fabs((a) - (b)) < EPSILON) if (FLOAT_EQUAL(x, y)) Brian Cripe ihnp4!hpfcla!hpvcla!brianc
bright@dataio.Data-IO.COM (Walter Bright) (03/17/87)
In article <16800001@qtecmuc.UUCP] ger@qtecmuc.UUCP writes:
] I had a similar problem today, with Microsoft C 4.0 on an IBM-AT compatible.
] The compiler tries to hold the result of the floor... statement in the
] 80 bit register of the 8087 and loads just b into another
] register for the comparison, if there is no other statement inbetween. Thus
] the compiler compares the 80-bit value resulting from previous operations and
] b, which is extended from 64 bit double precision to the internal 80 bit
] format, giving a!=b.
] My question: is this behaviour legal C ????
] Too much optimization in my eyes.
From a purist standpoint, I agree with you, but not from a practical one.
The code would expand considerably and would slow down a lot if the
8087 registers had to be stored and reloaded after every operation. I
think it's a tradeoff that most programmers would choose, since the
reason they are generating in-line 8087 code anyway is because they
want maximum speed.