Floating point formatted to base 16

I am writing a Lisp program to approximate pi using the Spigot algorithm, which finds one digit at a time without requiring any previously calculated digits. It:

Equation

Presumably one hexadecimal digit goes at a time, however, checking it, we have successive calls (iteration over i), giving Lisp known fractions :

2F / F, 6A / 333 33D / 4CB3 13C / 3B79

Etc. This is achieved using the format function with the ~ x parameter:

 (format t "~x" [some number])

As an alternative,

 (format t "~d" [some number])

Sets decimal decimal values :

3.1333334 0.12942614 0.042220525 0.020755336

, , 0.5, 0.8; 10 0,75, 0.C. , pi , Spigot. (n/16 ^ k), .

?

+3
2

~x ~d - , ( ):

22.3.2.2 D:

, , . ~ D .... arg , ~ A .

22.3.2.5 X:

, ~ D, (radix 16) .

( , , - , ~x , . , " , ~ D, " .)

? *print-base* *print-radix*, , :

*print-base*, *print-radix*

*print-base* *print-radix* . *print-base* .

*print-base* , . 10 9.

*print-radix* , , , . radix . *print-base* 2, 8 16, #b, #o #x, . base ten radix; # 10r.

format , 22.3.3. FORMAT. , , .

, . , , , , ~ slash, , :

(format t "~/hexadecimal/" 1/16)

, ( , ). (, + , @ , ..).

(in-package #:common-lisp-user)

(defun hexadecimal (stream number colonp atp &rest args)
  (declare (ignore colonp atp args))
  (when (< number 0)
    (write-char #\- stream)
    (setq number (- number)))
  (multiple-value-bind (quotient remainder) (floor number 1.0)
    (format stream "~x." quotient)
    (do () ((zerop remainder))
      (multiple-value-setq (quotient remainder)
        (floor (* 16 remainder)))
      (format stream "~x" quotient))))

:

(LOOP :FOR NUM :FROM -1/2 :TO 1/2 :BY 1/256
      :COLLECT (FORMAT NIL "~/hexadecimal/" NUM))
;=>
("-0.8" "-0.7F" "-0.7E" "-0.7D" "-0.7C" "-0.7B" "-0.7A" "-0.79" "-0.78"
 "-0.77" "-0.76" "-0.75" "-0.74" "-0.73" "-0.72" "-0.71" "-0.7" "-0.6F"
 ...
 "-0.1D" "-0.1C" "-0.1B" "-0.1A" "-0.19" "-0.18" "-0.17" "-0.16" "-0.15"
 "-0.14" "-0.13" "-0.12" "-0.11" "-0.1" "-0.0F" "-0.0E" "-0.0D" "-0.0C"
 "-0.0B" "-0.0A" "-0.09" "-0.08" "-0.07" "-0.06" "-0.05" "-0.04" "-0.03"
 "-0.02" "-0.01" "0." "0.01" "0.02" "0.03" "0.04" "0.05" "0.06" "0.07"
 "0.08" "0.09" "0.0A" "0.0B" "0.0C" "0.0D" "0.0E" "0.0F" "0.1" "0.11"
 ...
 "0.6C" "0.6D" "0.6E" "0.6F" "0.7" "0.71" "0.72" "0.73" "0.74" "0.75"
 "0.76" "0.77" "0.78" "0.79" "0.7A" "0.7B" "0.7C" "0.7D" "0.7E" "0.7F"
 "0.8")

, . , , *print-base* , , *print-base*:

(in-package #:common-lisp-user)

(defun floating (stream number colonp atp 
                 &optional (*print-base* 10) (num-digits 10)
                 &rest args)
  (declare (ignore colonp args))
  ;; If the number is negative, print the #\- and invert the number.
  ;; Otherwise, the number is non-negative, and if an @ was provided
  ;; we print a leading #\+.
  (cond
    ((minusp number)
     (write-char #\- stream)
     (setq number (- number)))
    (atp
     (write-char #\+ stream)))
  ;; Print number, which is now guaranteed to be positive.  Begin by
  ;; taking its integer part and printing it, followed by a point.
  ;; Then, pull individual places and write them.  This continues,
  ;; updating quotient and remainder by multiplying the remainder by
  ;; the base and taking the floor again until either the remainder
  ;; becomes zero, or we've reached the maximum number of digits.
  (multiple-value-bind (quotient remainder) (floor number 1.0)
    (write quotient :stream stream)
    (write-char #\. stream)
    (do ((num-digits num-digits (1- num-digits))) 
        ((or (zerop remainder) (zerop num-digits)))
      (multiple-value-setq (quotient remainder)
        (floor (* *print-base* remainder)))
      (write quotient :stream stream))))
;; 1/2 base 10 is a repeating decimal in base 3.
CL-USER> (format t "~3/floating/" 1/2)
0.1111111111

;; so is -1/2, and asking for more numbers gives them to us
CL-USER> (format t "~3,15/floating/" -1/2)
-0.111111111111111

;; but 1/3 base 10 is non repeating in base 3
CL-USER> (format t "~3,15/floating/" 1/3)
0.1

;; it non-repeating in base 6, as well
CL-USER> (format t "~6,15/floating/" 1/3)
0.2

;; base 16 still works
CL-USER> (format t "~16/floating/" 189/256)
0.BD

;; and the @ will give us a leading +
CL-USER> (format t "~16@/floating/" 189/256)
+0.BD
+5

, format 1 , - .


1. SBCL v1.1.14. (format t "~x" (coerce 2/32 'float)), , (format t "~d" (coerce 2/32 'float))

+1

All Articles