Subject: Re: separating on the decimal point
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 02 May 2009 21:24:57 -0500
Newsgroups: comp.lang.lisp
Message-ID: <OuednegWVanknWDUnZ2dnUVZ_hGdnZ2d@speakeasy.net>
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