~x ~d - , ( ):
, , . ~ D .... arg , ~ A .
, ~ D, (radix 16) .
( , , - , ~x , . , " , ~ D, " .)
? *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
(defun hexadecimal (stream number colonp atp &rest args)
(declare (ignore colonp atp args))
(when (< number 0)
(write-char
(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
(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
;; Otherwise, the number is non-negative, and if an @ was provided
;; we print a leading
(cond
((minusp number)
(write-char
(setq number (- number)))
(atp
(write-char
;; 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