home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!usc!news.service.uci.edu!unogate!mvb.saic.com!info-tex
- From: Phil Hirschhorn <PHIRSCHHORN@LUCY.WELLESLEY.EDU>
- Newsgroups: comp.text.tex
- Subject: Re: Two questions
- Message-ID: <8CE5A0B1A040D0E4@LUCY.WELLESLEY.EDU>
- Date: Mon, 25 Jan 1993 22:59 EST
- Organization: Info-Tex<==>Comp.Text.Tex Gateway
- X-Gateway-Source-Info: Mailing List
- Lines: 104
-
- This is a solution to one of Michael Barr's questions. \commas is a
- macro that takes one argument, which can be either a number or a
- counter, and prints that argument with commas separating groups of
- three digits. Thus, \commas{1234567} and
-
- \newcounter\mycounter
- \mycounter=1234567
- \commas{\mycounter}
-
- both produce 1,234,567.
-
- The partial solutions posted so far take the approach of doing
- arithmetic on the number to peel off the high order digit. Here, we
- just treat the number as a string of symbols, and peel them off one
- at a time.
-
- In outline:
-
- Check to see if the argument is a number or a counter. In either
- case, define \expanded so that it expands to the string of digits we
- want to print.
-
- Count the digits in the string, and store the result in \numdigits.
-
- Reduce \numdigits mod 3 (i.e., find the remainder on dividing
- \numdigits by 3).
-
- Print the digits one at a time, using \numdigits to keep track of
- when we should insert a comma.
-
-
- We intentionally never assign the argument of \commas to a counter,
- since the upper limit on the value of a counter in TeX is
- 2,147,483,647 = 2^{31}. This is why we must use \ifcat to test the
- catcode of 0 (a randomly chosen digit) against the catcode of the
- argument. Since the argument might be a string of digits (only the
- first of which would be eaten by \ifcat), we use \biggobble to clean
- up the mess left behind by the test.
-
- One other (possibly non-obvious) point below is that we usually keep
- \numdigits between 1 and 3, but when we start printing we have
- \numdigits equal to either 0, 1, or 2. This is to avoid printing a
- comma in front of a number like 123; We only print a comma when
- there are digits remaining and \numdigits=3. When we go to print the
- first digit, \numdigits is at most 2.
-
- There's no error checking here at all; A bad argument will probably
- make the whole thing blow up in your face. TeX isn't C, and I find
- it hard enough to get things to work even with good input.
-
- Phil Hirschhorn
- ----------------------------------------------------------------------
- \def\gobble#1{}
- \def\biggobble#1\relax{}
- \newcount\numdigits
-
- \def\commas#1{\expandafter\biggobble\ifcat0#1%
- % the argument is a digit string
- \relax\def\expanded{#1}%
- \else
- % the argument is a counter
- \relax\edef\expanded{\the#1}%
- \fi
- \countdigits\expanded
- \reducemodthree\numdigits
- \expandafter\dodigit\expanded\relax}
-
- \def\dodigit#1{\ifx#1\relax
- \let\next=\relax
- \else
- \ifnum\numdigits=3
- ,#1%
- \else
- #1%
- \fi
- \advance\numdigits by -1
- \ifnum\numdigits<1
- \advance\numdigits by3
- \fi
- \let\next=\dodigit
- \fi
- \next}
-
- \def\reducemodthree#1{\ifnum#1>2
- \advance#1 by -3
- \let\next=\reducemodthree
- \else
- \let\next=\gobble
- \fi
- \next#1}
-
- \def\countdigits#1{% #1 is a string of digits, or a macro
- % that expands to a string of digits
- \numdigits=0
- \expandafter\countem#1\relax}
-
- \def\countem#1{\ifx#1\relax
- \let\next=\relax
- \else
- \advance\numdigits by 1
- \let\next=\countem
- \fi
- \next}
-
-