double rounding in xtime_diff()?
Markus Kuhn
Markus.Kuhn at cl.cam.ac.uk
Mon Oct 12 22:24:06 UTC 1998
Paul Eggert wrote on 1998-10-12 19:57 UTC:
> > ``non-pathological'' = year range -9999 .. +9999
>
> OK, then here's a non-pathological example of a double-rounding error:
>
> 1970-01-01 00:00:01.851401618 UTC
> - 1970-01-01 00:00:00.000000000 UTC
>
> On the host that I'm talking about (sparc, IEEE, round-to-even)
> your xtime_diff implementation yields
> 1.851401618000000137698179969447664916515350341796875 exactly, whereas
> 1.8514016179999999156535750444163568317890167236328125, which is also
> exactly representable as an IEEE double, is closer to the correct answer.
That's very interesting. Under Linux/Pentium_II (cpu=686, model=3,
vendor_id=GenuineIntel, stepping=4, gcc 2.7.2.3) the effect does not
show up immediately. I had to enforce using the software FP-library with
gcc -msoft-float to reproduce this effect, because without this option
with the hardware FPU I get the correct result (and this is apparently
not thanks to Intel's internal 80-bit arithmetic, because I did use gcc
-ffloat-store to enforce 64-bit rounding).
There seem to be interesting differences between IEEE and IEEE.
-----------------------------------------------------------------------
#include <stdio.h>
typedef long long int_fast64_t;
typedef long int_fast32_t;
struct xtime {
int_fast64_t sec;
int_fast32_t nsec;
};
double xtime_diff(struct xtime t1, struct xtime t2)
{
if (t1.nsec > 1000000000) t1.nsec = 1000000000;
if (t2.nsec > 1000000000) t2.nsec = 1000000000;
return (t1.sec - t2.sec) + (t1.nsec - t2.nsec) / 1.0e9;
}
int main()
{
struct xtime t1 = { 1, 851401618 }, t2 = { 0, 0 };
double d;
d = xtime_diff(t1, t2);
printf("%.60f\n", d);
return 0;
}
-----------------------------------------------------------------------
Suggestions for a better portable implementation?
A somewhat related question: Given a floating-point value X,
is there in C9X a portable way to get the next smaller and the
next larger floating point value? Something like the Double'Succ(X)
and Double'Pred(X) built-in function attributes available in Ada
<http://wuarchive.wustl.edu/languages/ada/userdocs/docadalt/rm95/0305.htm>.
This might be very useful to write portable C code that is guaranteed to
deliver the closest value.
Markus
--
Markus G. Kuhn, Security Group, Computer Lab, Cambridge University, UK
email: mkuhn at acm.org, home page: <http://www.cl.cam.ac.uk/~mgk25/>
More information about the tz
mailing list