www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1994/11/06/05:57:22

To: Peter Csizmadia <cspt AT ludens DOT elte DOT hu>
Cc: djgpp AT sun DOT soe DOT clarkson DOT edu
Subject: Re: 2.4/3-2.4/3!=0
Date: Sun, 06 Nov 94 11:55:40 +0200
From: "Eli Zaretskii" <eliz AT is DOT elta DOT co DOT il>

> main()
>{
>   register double a1=2.4, b1=3.0;
>   volatile double a2=2.4, b2=3.0;
>   printf("2.4/3-2.4/3 = %le\n", a1/b1-a2/b2);
>}
>
> gcc a.c -lm -O1
> go32 a.out
> 2.4/3-2.4/3 = -3.70255041903800e-17
>
> Is it a normal effect of -O1? (a1=a2, b1=b2, a1/b1!=a2/b2)

As a general rule, floating point results should *never* be trusted
to be more accurate than a certain fraction of their magnitude.
This fraction is called ``machine epsilon'', and for double precision
64-bit numbers it is about 0.5e-16 (depends on the specifics of
the machine arithmetics).  You can find this number with the help of
the following fragment:

	double eps = 1.;
	while ((eps + 1.) != eps)
	    eps /= 2.;

(Don't compile with -O, it might not work!)

More specifically, in your case -O1 switch causes the expression
with a1 and b1 to be computed at compile time, but the volatile
variables are only computed at run time. Probably, one of these
computations uses full 80-bit precision of the i386 FPU, while the
other is only stored with 64 bits of precision.

But whatever the specifics, the above general rule should be *always*
kept in mind.

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019