From: Hallvard B Furuseth
Subject: How precise are floating-point operations?
Date:
Message-ID: <HBF.20030331q5mr@bombur.uio.no>
Is it possible to ask Lisp how precise its floating-point operations
are? Specifically, I need to know how much precision to trust
(log (coerce some-integer 'long-float) 2.0L0)
with in clisp.
I didn't find anything like DBL_EPSILON from <float.h> in C, so I tried
(defun float-epsilon-add (one dv)
(+ one dv)) ;don't want this optimized away
(defun float-epsilon (type)
(let* ((one (coerce 1 type))
(dv one))
(loop until (equal one (float-epsilon-add one dv))
do (setq dv (/ dv 2)))
dv))
That told me the precision of +, but I have no idea if it says that log
is equally precise, and I don't quite know how to do the same for log.
--
Hallvard
>>>>> "Hallvard" == Hallvard B Furuseth <············@usit.uio.no> writes:
Hallvard> Is it possible to ask Lisp how precise its floating-point operations
Hallvard> are? Specifically, I need to know how much precision to trust
Hallvard> (log (coerce some-integer 'long-float) 2.0L0)
Hallvard> with in clisp.
Probably pretty good, say within a couple of bits or so. But you'd
have to ask the clisp folks for the real answer.
Hallvard> I didn't find anything like DBL_EPSILON from <float.h> in C, so I tried
Hallvard> (defun float-epsilon-add (one dv)
Hallvard> (+ one dv)) ;don't want this optimized away
Hallvard> (defun float-epsilon (type)
Hallvard> (let* ((one (coerce 1 type))
Hallvard> (dv one))
Hallvard> (loop until (equal one (float-epsilon-add one dv))
Hallvard> do (setq dv (/ dv 2)))
Hallvard> dv))
Hallvard> That told me the precision of +, but I have no idea if it says that log
Hallvard> is equally precise, and I don't quite know how to do the same for log.
You could have gotten the same info[1] by looking at
single-float-epsilon, double-float-epsilon, etc.
Ray
Footnotes:
[1] Except for x86 which is a bit strange in this area with it's
habit of doing all FP arithmetic with 80-bit registers.
Hallvard B Furuseth wrote:
> Is it possible to ask Lisp how precise its floating-point operations
> are? Specifically, I need to know how much precision to trust
> (log (coerce some-integer 'long-float) 2.0L0)
> with in clisp.
I don't know of *any* language that exposes that sort of
information. As Raymond Toy already told you, you can get
the "machine epsilon" via <whatever>-FLOAT-EPSILON, but
that's not what you're after...
By the way, I take it you're aware that in CLISP[1] the
precision of long-floats can be increased without limit[2]?
If you're prepared to bet that LOG doesn't lose more than,
say, 16 bits of precision -- and I'd be *horrified* if it
were anywhere near that bad -- then you can just do
(setf (long-float-digits) N) where N is large enough
that even with whatever inaccuracy you expect LOG to
incur your calculations are safe.
Experiment suggests that CLISP always gives values
correct to within 1 ulp for LOG on long-floats.
Specifically, for all integers from 3 to 10000,
and on at least 10000 random integers below 10^9,
and on at least 2000 random integers below 2^256,
let A be the value computed with 256 bits and B
the value computed with 512; then -log_2(|A-B|/B)
is > 255 for all those numbers. I've done fewer
tests with other lengths, with similar results.
[1] I'm assuming that when you say "clisp" you mean the
Common Lisp implementation called "CLISP", not just
"Common Lisp".
[2] Well, almost :-).
--
Gareth McCaughan ················@pobox.com
.sig under construc
From: Hallvard B Furuseth
Subject: Re: How precise are floating-point operations?
Date:
Message-ID: <HBF.20030401d03n@bombur.uio.no>
Gareth McCaughan <················@pobox.com> wrote:
> I don't know of *any* language that exposes that sort of information.
Oops:-)
> As Raymond Toy already told you, you can get the "machine epsilon" via
> <whatever>-FLOAT-EPSILON, but that's not what you're after...
Yes, I hoped I had missed something like that.
> By the way, I take it you're aware that in CLISP[1] the precision of
> long-floats can be increased without limit[2]?
Well, I do now.
> If you're prepared to bet that LOG doesn't lose more than, say, 16
> bits of precision -- and I'd be *horrified* if it were anywhere near
> that bad -- then you can just do (setf (long-float-digits) N) where N
> is large enough that even with whatever inaccuracy you expect LOG to
> incur your calculations are safe. (...)
Done. Thanks.
--
Hallvard
Hi Hallvard B Furuseth,
> Is it possible to ask Lisp how precise its floating-point operations
> are? Specifically, I need to know how much precision to trust
> (log (coerce some-integer 'long-float) 2.0L0)
> with in clisp.
CLISP has arbitrary precision floats:
http://clisp.cons.org/impnotes/num-concepts.html#lfd
Some operators are precise to the arbitrary precision, like PI. Some less
so, like the implementation notes warn:
http://clisp.cons.org/impnotes/num-dict.html
"Function EXPT. (EXPT base exponent) is not very precise if exponent
has a large absolute value."
That limitation aside it appears to be as precise as you want:
[1]> (setf (ext:long-float-digits) 220)
220
[2]> (expt 2.0l0 (log 10.0l0 2.0L0))
WARNING:
Floating point operation combines numbers of different precision.
See ANSI CL 12.1.4.4 and the CLISP impnotes for details.
The result's actual precision is controlled by
*floating-point-contagion-ansi*.
To shut off this warning, set *warn-on-floating-point-contagion* to nil.
10.0000000000000000000000000000000000000000000000000000000000000000006L0
In long floating point CLISP really excels.
Regards,
Adam