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?
1 Answers
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.
- 259,911
- 34
- 706
- 1,036
\deflike lists are implemented, within a copy to another temporary\def( a length most probably) is needed) – Jan 20 '15 at 07:32\calc{1+2+3+4+5+6+...+1000+1001+1002+...}where\calcis from LaTeX/expl3(\ExplSyntaxOn \cs_new_eq:NN \calc \fp_eval:n \ExplSyntaxOff). – Werner Jan 20 '15 at 07:42\calc? – Jan 20 '15 at 07:43expl3uses about 5000 lines of code, is expandable and uses both e-TeX and a pdfTeX primitive. There are non-expandable maths systems in thefppackage andpgfmath: again both run to 1000s of lines. All three of these cover a lot more than addition, but even that probably needs 100s of lines. Doing the same thing in LuaTeX is trivial as Lua handles the maths. – Joseph Wright Jan 20 '15 at 08:19\Foldrand e-tex\numexpr. – morbusg Jan 20 '15 at 12:00\{1}\{2}\{3}
\showthe\temp
– David Mitra Jan 20 '15 at 12:19