Simple decimal precision problem

Discussion of Common Lisp

Simple decimal precision problem

Hi

I am implementing the Gauss-Legendre algorithm for approximating pi in common lisp. How do I use a long float? I have not been using lisp for very long and it automatically uses float and prints somewhere around 10-14 digits, but I want to generate and display many more digits than that.

I keep reading (setf (EXT:LONG-FLOAT) 2000) (or something like that) for instance, but I have not been able to get this to do anything.
Jope

Posts: 2
Joined: Sat Sep 10, 2011 5:08 pm

Re: Simple decimal precision problem

Common Lisp has no standardised functionality for that. I have never looked into that, but apparentlyCLISP has arbitrary precision floats. A solution portable between implementation would require implementing a custom numeric type.
ramarren

Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland

Re: Simple decimal precision problem

CL has a few float types. The default read format can be helpful when you don't want to type an explicit 1d0. Most implementations only really support single-float and double-float. I think Scieneer had a true long-float; but it appears to no longer be active.

nuntius

Posts: 536
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: Simple decimal precision problem

Thank you for the suggestions, I forgot to mention I am using GNU common lisp 2.6.7.

My problem is really how to go about specifying that double-float should be used for the calculations. Here is the simple algorithm as I have it currently:

Code: Select all
`; Computes an approximation of pi using the Gauss-Legendre method. Accuracy depending on input 'n'; eg. (GL 8)   -> 3.141592653589794;       (GL 30) -> 3.141592653589794(defun GL (n)  (GL_start 1 (/ 1 (sqrt 2)) (/ 1 4) 1 n))(defun GL_start (a b y z n)  (cond    ((eq n 0) (/ (sq (+ a b)) (* 4 y)))    (T (GL_start (/ (+ a b) 2) (sqrt (* a b)) (- y (* z (sq (- a (/ (+ a b) 2))))) (* 2 z) (- n 1)))  ))(defun sq (x)  (* x x))`

As you can see in the example, GL(8) has the same number of digits as GL(30), but I would like to be able to control the number of digits displayed depending on the inputted 'n'.
Thank you
Jope

Posts: 2
Joined: Sat Sep 10, 2011 5:08 pm

Re: Simple decimal precision problem

Jope wrote:My problem is really how to go about specifying that double-float should be used for the calculations.

For example use one of these:

Code: Select all
`(defun GL (n)  (GL_start 1 (/ 1 (sqrt 2.0d0)) (/ 1 4) 1 n))(defun GL (n)  (GL_start 1 (/ 1 (sqrt (the double-float 2.0))) (/ 1 4) 1 n))`

(Edit: do not use the second version, see below for the reasons why not.)

Jope wrote:As you can see in the example, GL(8) has the same number of digits as GL(30), but I would like to be able to control the number of digits displayed depending on the inputted 'n'.

If GNU_CL uses IEEE floats (what is very likely) then you're out of luck because then the number of digits is defined by IEEE and not by GNU_CL. The only possibilies would be either to artificially cripple the floats, e.g. by:

Code: Select all
`(defun digits-after-dot (float digits)  (let ((factor (* (expt 10 digits))))    (/ (ftruncate (* float factor)) factor)))  (digits-after-dot pi 3)  => 3.141(digits-after-dot pi 4)  => 3.1415(digits-after-dot pi 5)  => 3.14159`

But this is a rather wacky hack that will quickly raise "floating point overflow" errors, and will of course not display more digits than defined by IEEE.

The only other alternative is using "bigfloats", e.g:

• bf.lisp - Common Lisp Bigfloat Package by Richard Fateman

- edgar
Last edited by edgar-rft on Tue Sep 13, 2011 4:11 am, edited 1 time in total.
edgar-rft

Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: Simple decimal precision problem

edgar-rft wrote:
Code: Select all
`(defun GL (n)  (GL_start 1 (/ 1 (sqrt (the double-float 2.0))) (/ 1 4) 1 n))`

Don't do this. (the double-float 2.0) doesn't make it a double, it just tells the compiler it is one -- which is a lie unless you've set *read-default-float-format* to a non-default value. (I can't see how any harm can come from this lie, except that the result won't be what you expect; in fact, the compiler should know better; but in theory it's "monkeys from the nose" code)
Paul

Posts: 106
Joined: Tue Jun 02, 2009 6:00 am

Re: Simple decimal precision problem

@Jope: Paul is right, I worked too long with SBCL, where everything gets compiled before evaluation, but this trick doesn't work in all CL implementations, so it's better not to use (the double-float 2.0) with GNU_CL, where it probably doesn't work.

@Paul: thanks.
edgar-rft

Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: Simple decimal precision problem

You may want to look at the (high quality) OCT library http://common-lisp.net/project/oct/

MA
Marco Antoniotti
marcoxa

Posts: 85
Joined: Thu Aug 14, 2008 6:31 pm

Re: Simple decimal precision problem

Format allows you to control the number of digits printed by the format string "~0,<n>E" where <n> is the number of digits.

Code: Select all
`(defun print-float (f &optional (n 0))  (format t (format nil "~~0,~DE" n) f))`
Konfusius

Posts: 62
Joined: Fri Jun 10, 2011 6:38 am