Tamas K Papp <tkpapp@gmail.com> wrote:
+---------------
| I am generating LaTeX tables of numbers, and I am aligning the numbers
| on the decimal point (using the standard r@{}l trick). For that I
| need to separate them into 2 parts, one before and one after (and
| including) the decimal point, and I also constrain the number of
| digits in the latter.
|
| The best solution I could come up with was extracting from the output
| of format, like this:
|
| (defun float-2part (x digits)
| (multiple-value-bind (int frac) (truncate x)
| (values (format nil "~d" int)
| (if (plusp digits)
| (subseq (format nil "~,vf" digits (abs frac)) 1)
| ""))))
|
| Examples:
|
| (float-2part pi 2) ; "3", ".14"
| (float-2part (- pi) 2) ; "-3", ".14"
| (float-2part 1239.93 3) ; "1239", ".930"
| (float-2part -1239.93 3) ; "-1239", ".930"
| (float-2part pi 0) ; "3", ""
|
| This works fine, and it does not need to be fast. I am just asking if
| there is a more elegant way I missed.
+---------------
Not more elegant, but perhaps a tiny bit simpler:
(defun float-2part (x digits)
(let* ((string (format nil "~,vf" digits x))
(pos (position #\. string)))
(values (subseq string 0 pos)
(if (plusp digits) (subseq string pos) ""))))
I don't know exactly what you need for your table, but given that
you already know the number of fractions digits you want to display,
you could simply supply the filler in a single FORMAT and not have
to take stuff apart and put it back together again, e.g.:
> (defun float-align-dot (x digits max-digits width)
(let* ((rfill (- max-digits digits))
(lfill (- width rfill)))
(format t "~v,vf~va~%" lfill digits x rfill " ")))
FLOAT-ALIGN-DOT
> (loop for v in (list pi (- pi) 1239.93 -1239.93 pi)
and d in '(2 2 3 3 0) do
(float-align-dot v d 5 12))
3.14
-3.14
1239.930
-1239.930
3.
NIL
>
[Yes, I see that this fails to suppress the "." on the last entry,
but I wasn't sure whether that was a hard requirement or not.]
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607