Simple decimal precision problem
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.
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.
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.
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.
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:
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
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)
)
Thank you
Re: Simple decimal precision problem
For example use one of these:Jope wrote:My problem is really how to go about specifying that double-float should be used for the calculations.
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))
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: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'.
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
The only other alternative is using "bigfloats", e.g:
- bf.lisp - Common Lisp Bigfloat Package by Richard Fateman
Last edited by edgar-rft on Tue Sep 13, 2011 4:11 am, edited 1 time in total.
Re: Simple decimal precision problem
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)edgar-rft wrote:Code: Select all
(defun GL (n) (GL_start 1 (/ 1 (sqrt (the double-float 2.0))) (/ 1 4) 1 n))
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.
@Paul: thanks.
Re: Simple decimal precision problem
Marco Antoniotti
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))