home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / text / tex / 15443 < prev    next >
Encoding:
Text File  |  1993-01-26  |  3.9 KB  |  115 lines

  1. Path: sparky!uunet!usc!news.service.uci.edu!unogate!mvb.saic.com!info-tex
  2. From: Phil Hirschhorn <PHIRSCHHORN@LUCY.WELLESLEY.EDU>
  3. Newsgroups: comp.text.tex
  4. Subject: Re: Two questions
  5. Message-ID: <8CE5A0B1A040D0E4@LUCY.WELLESLEY.EDU>
  6. Date: Mon, 25 Jan 1993 22:59 EST
  7. Organization: Info-Tex<==>Comp.Text.Tex Gateway
  8. X-Gateway-Source-Info: Mailing List
  9. Lines: 104
  10.  
  11. This is a solution to one of Michael Barr's questions.  \commas is a
  12. macro that takes one argument, which can be either a number or a
  13. counter, and prints that argument with commas separating groups of
  14. three digits.  Thus,  \commas{1234567} and
  15.  
  16. \newcounter\mycounter
  17. \mycounter=1234567
  18. \commas{\mycounter}
  19.  
  20. both produce 1,234,567.
  21.  
  22. The partial solutions posted so far take the approach of doing
  23. arithmetic on the number to peel off the high order digit.  Here, we
  24. just treat the number as a string of symbols, and peel them off one
  25. at a time.
  26.  
  27. In outline:
  28.  
  29. Check to see if the argument is a number or a counter. In either
  30. case, define \expanded so that it expands to the string of digits we
  31. want to print.
  32.  
  33. Count the digits in the string, and store the result in \numdigits.
  34.  
  35. Reduce \numdigits mod 3 (i.e., find the remainder on dividing
  36. \numdigits by 3).
  37.  
  38. Print the digits one at a time, using \numdigits to keep track of
  39. when we should insert a comma.
  40.  
  41.  
  42. We intentionally never assign the argument of \commas to a counter,
  43. since the upper limit on the value of a counter in TeX is
  44. 2,147,483,647 = 2^{31}.  This is why we must use \ifcat to test the
  45. catcode of 0 (a randomly chosen digit) against the catcode of the
  46. argument.  Since the argument might be a string of digits (only the
  47. first of which would be eaten by \ifcat), we use \biggobble to clean
  48. up the mess left behind by the test.
  49.  
  50. One other (possibly non-obvious) point below is that we usually keep
  51. \numdigits between 1 and 3, but when we start printing we have
  52. \numdigits equal to either 0, 1, or 2.  This is to avoid printing a
  53. comma in front of a number like 123; We only print a comma when
  54. there are digits remaining and \numdigits=3.  When we go to print the
  55. first digit, \numdigits is at most 2.
  56.  
  57. There's no error checking here at all; A bad argument will probably
  58. make the whole thing blow up in your face.  TeX isn't C, and I find
  59. it hard enough to get things to work even with good input.
  60.  
  61. Phil Hirschhorn
  62. ----------------------------------------------------------------------
  63. \def\gobble#1{}
  64. \def\biggobble#1\relax{}
  65. \newcount\numdigits
  66.  
  67. \def\commas#1{\expandafter\biggobble\ifcat0#1%
  68.                  % the argument is a digit string
  69.                  \relax\def\expanded{#1}%
  70.               \else
  71.                  % the argument is a counter
  72.                  \relax\edef\expanded{\the#1}%
  73.               \fi
  74.               \countdigits\expanded
  75.               \reducemodthree\numdigits
  76.               \expandafter\dodigit\expanded\relax}
  77.  
  78. \def\dodigit#1{\ifx#1\relax
  79.                   \let\next=\relax
  80.                \else
  81.                   \ifnum\numdigits=3
  82.                      ,#1%
  83.                   \else
  84.                      #1%
  85.                   \fi
  86.                   \advance\numdigits by -1
  87.                   \ifnum\numdigits<1
  88.                      \advance\numdigits by3
  89.                   \fi
  90.                   \let\next=\dodigit
  91.                \fi
  92.                \next}
  93.  
  94. \def\reducemodthree#1{\ifnum#1>2
  95.                           \advance#1 by -3
  96.                           \let\next=\reducemodthree
  97.                       \else
  98.                           \let\next=\gobble
  99.                       \fi
  100.                       \next#1}
  101.  
  102. \def\countdigits#1{%   #1 is a string of digits, or a macro
  103.                    %      that expands to a string of digits
  104.            \numdigits=0
  105.                    \expandafter\countem#1\relax}
  106.  
  107. \def\countem#1{\ifx#1\relax
  108.                   \let\next=\relax
  109.                \else
  110.                   \advance\numdigits by 1
  111.                   \let\next=\countem
  112.                \fi
  113.                \next}
  114.  
  115.