2

How would I go about implementing a function in TeX to add an arbitrary number of numbers? Reading through the \def notes, it seems it can only take up to nine arguments. How would I make a function that adds together an optionally arbitrarily large list of numbers?

13
  • 1
    Perhaps a Recursive \def like lists are implemented, within a copy to another temporary \def ( a length most probably) is needed)
    – user31729
    Jan 20 '15 at 7:32
  • You should be more specific in terms of the input requirements. So, mock up some example and show what you've tried.
    – Werner
    Jan 20 '15 at 7:37
  • Related (like a distant cousin): Sum of finite series
    – Werner
    Jan 20 '15 at 7:37
  • @Werner I suppose I should have asked a more basic question then, I'm still really trying to figure out how TeX works, and I was hoping seeing something like this would get me started.
    – user41692
    Jan 20 '15 at 7:38
  • 3
    TeX's not really set up for doing mathematics (it's good at typesetting maths!). As Werner says, you'll need to tighten up the spec of what you want to achieve. For example, are we talking integers or floating-point values, and if so how many digits? Do you need an expandable solution (one that can be used inside a context that 'expects' a number)? Can we use e-TeX/pdfTeX/LuaTeX or do you want a solution for Knuth's TeX? As indicated, a mock-up of the use case(s) and expected results would be very handy.
    – Joseph Wright
    Jan 20 '15 at 8:15
5

I will answer on the assumption that the input will be of the form

\addintegers{1 + 2 + 3}

i.e. consisting of a series of integers separated by + symbols and (potentially) whitespace. I'm also going to assume the solution does not need to be expandable, that we have only the TeX3 primitives available, and that we do not have to worry about 'big' values (larger than can be held by a \count register).

To find the sum here we need to set up a loop over the input, grabbing one number at a time. As we know that + comes between each number, the way to do that is to use a macro of the form

\def\foo#1+{% Code

as this will grab everything up to the next +. We then need to make sure that there is a + after the user input and that we have some 'marker' there we can test for as 'end-of-loop'. To do the actual maths, TeX provides \count registers: I'll use a scratch on inside a group and emit the result outside of the group using \expandafter:

\catcode`\@=11 %
\def\addintegers#1{%
  \begingroup
    \count0=0\relax
    \addintegers@aux#1+\relax+\relax
}
\def\addintegers@aux#1+{%
  \ifx\relax#1\relax
    \expandafter\addintegers@end
  \else
    \advance\count0 by #1\relax
    \expandafter\addintegers@aux
  \fi
}
\def\addintegers@end#1\relax{%
  \expandafter\endgroup
  \number\count0 %
}
\catcode`\@=12 %
\addintegers{1}
\addintegers{1 + 2 + 3}
\addintegers{1 + 22 + 333}
\bye

This is of course a rather restricted solution (no coverage for example of subtraction unless there is a + sign too) but more detail would be needed in the question to go further. Full error-checking would need something a bit more complex.

If the e-TeX primitives are available the same can be achieved expandably with virtually no effort

\def\inteval#1{\number\numexpr#1\relax}
\inteval{1}
\inteval{1 + 2 + 3}
\inteval{1 + 22 + 333}
\bye

in which case the calculation can include +, -, *, /, ( and ) as supported by e-TeX (hence the different name). (e-TeX also allows whitespace in expressions.)


If you want to work expandably and to use only Knuth's TeX then it is doable if a bit tedious. Heiko Oberdiek's bigintcalc can do calculations on arbitrary integers expandably and without using e-TeX, so we could harness that (it's quite big):

\input bigintcalc.sty %
\catcode`\@=11 %
\def\addintegers#1{%
  \addintegers@auxi#1+\relax+\stop{0}%
}
\def\addintegers@auxi#1+{%
  \ifx\relax#1%
    \expandafter\addintegers@end
  \else
    \expandafter\addintegers@auxii
  \fi
    {#1}%
}
\def\addintegers@auxii#1#2\stop#3{%
  \addintegers@auxi#2\stop{\bigintcalcAdd{#1}{#3}}%
}
\def\addintegers@end#1\stop#2{#2}
\catcode`\@=12 %
\addintegers{1}
\addintegers{1 + 2 + 3}
\addintegers{1 + 22 + 333}

\bye

The detail in bigintcalc comes down to splitting the input into individual digits and doing the maths 'by hand' if \numexpr is not available.

1
  • Thank you so much for the response, I'll read through this.
    – user41692
    Jan 20 '15 at 8:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy