How to get the sum, difference, product, and quotient from a macro in ConTeXt or Plain TeX?
You can use the ε-TeX primitive \numexpr
for expandable integer expressions. The only restriction is that it won't work in engines without ε-TeX extensions (mostly Knuth TeX nowadays), in which case you need to go with siracusa's solution.
These macros being expandable, allows you to use them anywhere TeX expects a number, like in \ifnum
, \ifcase
, or \ifdim
(with the proper units) tests, register assignments, etc.
Here are the four interfaces you want (I swapped the order of the arguments in \dividenumbers
because I think it makes more sense this way), plus a generic \inteval
, which takes an integer expression, like 2+5*(3-4)
, as argument:
\def\addnumbers#1#2{\number\numexpr#1+#2\relax}
\def\subtractnumbers#1#2{\number\numexpr#1-#2\relax}
\def\multiplynumbers#1#2{\number\numexpr#1*#2\relax}
\def\dividenumbers#1#2{\number\numexpr#1/#2\relax}
\def\inteval#1{\number\numexpr#1\relax}
\def\test#1#2#3#4{$#2#3#4 = #1{#2}{#4}$\par}
\test\addnumbers{2}+{5}
\test\subtractnumbers{3}-{5}
\test\multiplynumbers{2}\times{-2}
\test\dividenumbers{8}\div{2}
$2+5\times(3-4) = \inteval{2+5*(3-4)}$
\bye
If you don't want to restrict yourself to integers, you can use expl3
's FPU, which is format-independent, and also expandable. It allows you a much larger range of operations. The code below defines the four interfaces you asked, plus \fpeval
for generic floating point expressions (in LaTeX the package xfp
provides the same \fpeval
):
\input expl3-generic.tex
\ExplSyntaxOn
\cs_new:Npn \addnumbers #1 #2
{ \fp_eval:n { #1 + #2 } }
\cs_new:Npn \subtractnumbers #1 #2
{ \fp_eval:n { #1 - #2 } }
\cs_new:Npn \multiplynumbers #1 #2
{ \fp_eval:n { #1 * #2 } }
\cs_new:Npn \dividenumbers #1 #2
{ \fp_eval:n { #1 / #2 } }
\cs_new:Npn \fpeval #1
{ \fp_eval:n { #1 } }
\ExplSyntaxOff
\def\test#1#2#3#4{$#2#3#4 = #1{#2}{#4}$\par}
%
\test\addnumbers{2}+{5}
\test\subtractnumbers{3}-{5}
\test\multiplynumbers{2}\times{-2}
\test\dividenumbers{8}\div{2}
$2^2+5\times(\cos(3)-4) = \fpeval{2^2+5*(cos(3)-4)}$
\bye
As you haven't specified if the solution should be expandable, here's a non-expandable plain TeX solution.
We first define a general \docalc
macro which takes a calculation command working on count registers (\advance
, \multiply
or \divide
), and the two operands. The operation is applied on a local register which value is immediately output afterwards. Based on \docalc
we then define the four macros for doing the basic arithmetic operations:
\def\docalc#1#2#3{%
\begingroup
\count0=#3
#1\count0 by #2\relax
\the\count0
\endgroup
}
\def\addnumbers {\docalc\advance}
\def\subtractnumbers#1{\docalc\advance{-#1}}
\def\multiplynumbers {\docalc\multiply}
\def\dividenumbers {\docalc\divide}
$2 + 5 = \addnumbers{2}{5}$
$5 - 3 = \subtractnumbers{3}{5}$
$2 \cdot (-2) = \multiplynumbers{2}{-2}$
$8 \div 2 = \dividenumbers{2}{8}$
\bye
In ConTeXt you can use the lua interface:
\starttext
The first will display the number \ctxlua{context(2+5)}
\stoptext