From: Tamas K Papp
Subject: separating on the decimal point
Date: 
Message-ID: <7634a0F1ajv9aU1@mid.individual.net>
Hi,

I am generating LaTeX tables of numbers, and I am aligning the numbers
on the decimal point (using the standard ·@{}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.

Tamas

From: Rob Warnock
Subject: Re: separating on the decimal point
Date: 
Message-ID: <OuednegWVanknWDUnZ2dnUVZ_hGdnZ2d@speakeasy.net>
Tamas K Papp  <······@gmail.com> wrote:
+---------------
| I am generating LaTeX tables of numbers, and I am aligning the numbers
| on the decimal point (using the standard ·@{}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.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Tamas K Papp
Subject: Re: separating on the decimal point
Date: 
Message-ID: <7668osF1bl3sbU1@mid.individual.net>
On Sat, 02 May 2009 21:24:57 -0500, Rob Warnock wrote:

> Tamas K Papp  <······@gmail.com> wrote: +---------------
> | I am generating LaTeX tables of numbers, and I am aligning the numbers
> | on the decimal point (using the standard ·@{}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) ""))))

Thanks, your version has the extra advantage of being correct :-) Mine
did not format values in (-1,0) correctly (missed the minus sign).

I also found a bug in the SBCL formatter:

(format nil "~,2f" 2.219822937194833d-6)

in SBCL gives

"0.000"

which I already reported to their mailing list.  Formatting is hard,
no wonder there is a DSL for it.

> 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.:

Thanks, but I am generating a LaTeX table.  There is a well-known
trick of using a column spec like ·@{}l and then writing 3.14 and
27.91 as

3 & .14 \\
27 & .91 \\

which will then be aligned on the decimal dot.  It was quite easy to
generate these with CL, now I can have a script spit out about ten
10x21 tables when the calculations are complete.

Thanks,

Tamas
From: Andreas Eder
Subject: Re: separating on the decimal point
Date: 
Message-ID: <87vdnq7dec.fsf@eder.homelinux.net>
Hi Tamas,

>>>>> "Tamas" == Tamas K Papp <······@gmail.com> writes:

    Tamas> On Sat, 02 May 2009 21:24:57 -0500, Rob Warnock wrote:
    >> Tamas K Papp  <······@gmail.com> wrote: +---------------
    >> | I am generating LaTeX tables of numbers, and I am aligning the
    Tamas> numbers
    >> | on the decimal point (using the standard ·@{}l trick). For that I
    Tamas> |
    >> 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
    Tamas> 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
    Tamas> 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) ""))))

    Tamas> Thanks, your version has the extra advantage of being correct :-) Mine
    Tamas> did not format values in (-1,0) correctly (missed the minus sign).

    Tamas> I also found a bug in the SBCL formatter:

    Tamas> (format nil "~,2f" 2.219822937194833d-6)

    Tamas> in SBCL gives

    Tamas> "0.000"

    Tamas> which I already reported to their mailing list.  Formatting is hard,
    Tamas> no wonder there is a DSL for it.

    >> I don't know exactly what you need for your table, but given that
    Tamas> 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
    Tamas> take
    >> stuff apart and put it back together again, e.g.:

    Tamas> Thanks, but I am generating a LaTeX table.  There is a well-known
    Tamas> trick of using a column spec like ·@{}l and then writing 3.14 and
    Tamas> 27.91 as

    Tamas> 3 & .14 \\
    Tamas> 27 & .91 \\

    Tamas> which will then be aligned on the decimal dot.  It was quite easy to
    Tamas> generate these with CL, now I can have a script spit out about ten
    Tamas> 10x21 tables when the calculations are complete.

    Tamas> Thanks,

    Tamas> Tamas

Hi, I may be a little late with my suggestion, but have you had a
look at the dcolumn package of David Carlisle?
I think that might be just what you need:
http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=dcolumn

Andreas

-- 
ceterum censeo redmondinem esse delendam.
From: Tamas K Papp
Subject: Re: separating on the decimal point
Date: 
Message-ID: <77ta4tF1jo9smU1@mid.individual.net>
On Sun, 24 May 2009 17:02:03 +0200, Andreas Eder wrote:

> Hi, I may be a little late with my suggestion, but have you had a look
> at the dcolumn package of David Carlisle? I think that might be just
> what you need:
> http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=dcolumn

Hi Andreas,

Thanks.  I might just rework my latex-table library to use dcolumn.

Tamas
From: Thomas A. Russ
Subject: Re: separating on the decimal point
Date: 
Message-ID: <ymizldsem72.fsf@blackcat.isi.edu>
Tamas K Papp <······@gmail.com> writes:

> Hi,
> 
> I am generating LaTeX tables of numbers, and I am aligning the numbers
> on the decimal point (using the standard ·@{}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 bdigits)
>   (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.

Actually, I don't think this works fine.  Consider what happens with

  (float-2part 12.996 2)   =>  "12" ".00"

I would think that the best solution would be to just do the format
fully using the ~f format statement and then split it on the decimal
point from the string, by searching for ".".  That way you let the
formatting code take care of the rounding and layout for you, instead of
figuring it out all for yourself.

If you want to suppress trailing zeroes, then you will need to do a
further test on the fractional part:

(defun float-2part (x bdigits)
  (let* ((float-string (format nil "~,vf" bdigits x))
	 (decimal-pos (position #\. float-string))
	 (fraction-string (subseq float-string decimal-pos)))

    ;; Optional filters here

    (values (subseq float-string 0 decimal-pos) fraction-string)))

You can then add filtering tests to suppress the fractional part if
bdigits is zero:

  (when (zerop bdigits)
    (setq fraction-string ""))

and also perhaps truncate the fraction if there are only zeroes:

  (when (= (count #\0 fraction-string) bdigits)
    (setq fraction-string ""))   ; or ".0"



-- 
Thomas A. Russ,  USC/Information Sciences Institute