# Parse simple arithmetics and return the result

I want a command \ca which takes a simple arithmetic calculation as an argument and returns the result with proper decimal places. Additionally I want an boolean argument which decides if only the result is printed or the whole calculation.

For example

\ca{8.12 - 2.2 + 1}

should just print 6.92.

or

\ca[t]{8.12 - 2.2 + 1}

should print 8.12 - 2.2 + 1 = 6.92

Following the question How can I sum two values and store the result in other variable? I did this:

\documentclass{article}
\usepackage[nomessages]{fp}% http://ctan.org/pkg/fp
\usepackage{ifthen}

\newcommand{\ca}[2][f]{
\FPeval{\result}{clip(#2)}
\ifthenelse{\equal{#1}{t}}{
$#2= \result$}
{
\result
}
}

\begin{document}
\ca[t]{3*(2.2 + 2.3)}

\ca{2.5 + 2.78}
\end{document}


Is it possible to to the same such that the german comma notation is used in what is displayed (i.e. 8,2 instead of 8.2) and in the case the calculation is printed that * is printed as \dcot.

-
Please take a look at How can I sum two values and store the result in other variable? as the answers there might help you. If they do, that's great, and we'll probably close this question as a duplicate just to keep the place tidy and to help people find the answers quickly. If they don't, please edit your question here to explain why so that people can better focus their attention to help you. –  Werner Nov 29 '11 at 20:40
As @Werner says, the basics of the calculation are probably covered elsewhere. Something like the Boolean you ask about would be handled by absorbing the argument, doing the calculation then deciding what to print based on a switch. There are questions about that here too, or you might ask something focussed just on the one issue. –  Joseph Wright Nov 29 '11 at 20:50
Ok, thanks, Werner's suggestion helped, I will change my question to address the remaining obscurities –  student Nov 29 '11 at 20:58
See also tex.stackexchange.com/questions/13333/…, I have a similar example in the question. –  Yiannis Lazarides Nov 30 '11 at 6:20

Here is a crude way of modifying the output to be \cdot and ,-specific using xstring. The reason for using xstring is because the argument to fp (#2) would otherwise have to be parsed and separated into operators and operands to enable numprint usage (say).

\documentclass{article}
\usepackage[nomessages]{fp}% http://ctan.org/pkg/fp
\usepackage{xstring}% http://ctan.org/pkg/xstring
\usepackage{xparse}% http://ctan.org/pkg/xparse

\NewDocumentCommand{\ca}{s m}{
\FPeval{\result}{clip(#2)}
\IfBooleanTF{#1}% Condition on starred/unstarred version
{% starred version \ca*{...}
\StrSubstitute{\result}{.}{,}
}{% unstarred version \ca{...}
\StrSubstitute{#2}{.}{,\!}[\temp]% '.' -> ','
\StrSubstitute{\temp}{*}{\cdot}[\temp]% '*' -> '\cdot'
$\temp=\StrSubstitute{\result}{.}{,\!}$
}
}

\begin{document}
\ca{3*(2.2 + 2.3)}

\ca*{2.5 + 2.78}
\end{document}​


xparse was used to provide a starred/unstarred version of \ca where the unstarred version \ca prints the expression, while the starred version \ca* does not.

-

I think you mean \cdot not \dot. In this case you may use:

\documentclass{article}
\usepackage[nomessages]{fp}% http://ctan.org/pkg/fp
\usepackage{ifthen}

\begingroup
\catcode\.=\active
\catcode\*=\active
\newcommand{\germannotation}[1]{%
\begingroup
\catcode\.=\active
\def.{{,}}%
\catcode\*=\active
\def*{\cdot}%
\scantokens{#1}%
\endgroup
}
\global\let\germannotation\germannotation
\endgroup

\newcommand{\ca}[2][f]{%
\FPeval{\result}{clip(#2)}%
\edef\result{\noexpand\germannotation{\result}}%
\ifthenelse{\equal{#1}{t}}{%
$\germannotation{#2}=\result$%
}{%
\result
}%
}

\begin{document}
\ca[t]{3*(2.2 + 2.3)}

\ca{2.5 + 2.78}
\end{document}

-
Nice - this is great! –  Werner Nov 29 '11 at 22:15

This is a simplified version of Schweinebacke's solution (and a case where \ensuremath can be justified):

\documentclass[a4paper]{article}
\usepackage{xparse,fp}
\def\changecommaandstar{%
\mathcode.=\string"8000
\mathcode*=\string"8000
\begingroup\lccode~=.\lowercase{\endgroup\def~}{{,}}
\begingroup\lccode~=*\lowercase{\endgroup\def~}{\cdot}
}
\NewDocumentCommand{\ca}{sm}{%
\ensuremath{\begingroup
\FPeval{\result}{clip(#2)}
\changecommaandstar
\IfBooleanT{#1}{#2=}\result
\endgroup}
}

\begin{document}

\ca*{3*(2.2 + 2.3)}

$\ca{2.5 + 2.78}>5$

\end{document}


This is also a case where a *-version, rather than an optional argument, is perhaps better.

-

Here is a version that use pgf for the math calculations which allows for more complicated math expressions (such as tan(deg(pi/4)) below), and the numprint package for the formatting of the output:

## Notes:

• The german formatting of the input and changing the * in the input to a \cdot (adding pi, \tan, etc...) is adapted form @Werner's solution.

## Futher Enhancements:

• Use numprint for the numbers in the input as that allows for more flexibility than just changing the . to a ,.
• Handle formatting of more complex mathematical expressions, for instance change exp(a/b) to \e^{a/b}

## Code:

\documentclass{article}
\usepackage{pgf}
\usepackage{xparse}
\usepackage{xstring}
\usepackage{numprint}

\StrSubstitute{#1}{.}{,\!}[\temp]%
\StrSubstitute{\temp}{*}{\cdot}[\temp]%
\StrSubstitute{\temp}{sin}{\sin}[\temp]%
\StrSubstitute{\temp}{cos}{\cos}[\temp]%
\StrSubstitute{\temp}{tan}{\tan}[\temp]%
\StrSubstitute{\temp}{deg}{}[\temp]%
\StrSubstitute{\temp}{((}{(}[\temp]%
\StrSubstitute{\temp}{))}{)}[\temp]%
\StrSubstitute{\temp}{pi}{\pi}[\temp]%
\temp%
}%

\NewDocumentCommand{\ca}{s m}{%
\pgfmathsetmacro{\var}{#2}%
\IfBooleanTF{#1}{%
\ensuremath{\numprint{\var}}%
}{%
}%
}%

\begin{document}
\ca*{8.12 - 2.2 + 1}% starred version only prints result

\ca{3*(2.2 + 2.3)}

\ca{8.12 - 2.2 + tan(deg(pi/4))}
\end{document}

-
As you see, I can use \ensuremath sometimes. :) –  egreg Nov 30 '11 at 0:15
@egreg: :-) I saw that in you answer, but was waiting to see if you would recommend I remove it here. :-) –  Peter Grill Nov 30 '11 at 0:28
@PeterGrill: Note though that your expression still does not show commas since \numprint is only applied to the answer. –  Werner Nov 30 '11 at 3:28
@Werner: I did not read that that was required by the OP, but have adapted your solution for that. –  Peter Grill Nov 30 '11 at 5:40

I'm a little hesitant in adding this answer, as I'm merely fumbling my way around with Lua. Feel free to edit and improve the code.

Anyways, as implied above, here is a way that requires compilation with lualatex, as the calculation is done with Lua.

\documentclass{article}
\usepackage{luacode}
\newcommand{\ca}[2][f]{%
\luaexec{
check = "#1"
input = #2
calculation = "#2"
calculation = string.gsub(calculation, "*", "\\cdot ")
calculation = string.gsub(calculation, "\%.", "{,}")
if check == "f" then
else
end
}}
\begin{document}
\ca{1+2.2 - 5/2} \par
\ca[t]{3+1-2.34*3}
\end{document}


This could also be expanded to allow sin, cos, etc. by changing the definition of the command to

\newcommand{\ca}[2][f]{%
\luaexec{
local sin, cos, tan, pi, exp, ln, log = math.sin, math.cos, math.tan, math.pi, math.exp, math.log, math.log10
check = "#1"
input = #2
calculation = "#2"
calculation = string.gsub(calculation, "*", "\\cdot ")
calculation = string.gsub(calculation, "\%.", "{,}")
calculation = string.gsub(calculation, "pi*", "\\pi ")
calculation = string.gsub(calculation, "sin", "\\sin ")
calculation = string.gsub(calculation, "cos", "\\cos ")
calculation = string.gsub(calculation, "tan", "\\tan ")
calculation = string.gsub(calculation, "exp", "\\exp ")
calculation = string.gsub(calculation, "ln", "\\ln ")
calculation = string.gsub(calculation, "log", "\\log ")
if check == "f" then
else
end
}}

-

Here is something I fooled around with. I became aware of your question afterwards, so it is only a partial answer. It uses the new l3fp package of expl3.

\documentclass{article}
\usepackage{xparse}
\begin{document}

\ExplSyntaxOn

\cs_new:Npn \typeset_eq:n #1 {
\tl_set:Nn \l_tmpa_tl { #1 }
\tl_set_eq:NN \l_tmpb_tl \l_tmpa_tl
\tl_replace_all:Nnn \l_tmpb_tl { * } { \times }
\tl_replace_all:Nnn \l_tmpb_tl { pi } { \pi }
\tl_replace_all:Nnn \l_tmpb_tl { sin } { \sin }
\tl_replace_all:Nnn \l_tmpb_tl { cos } { \cos }
\tl_replace_all:Nnn \l_tmpb_tl { tan } { \tan }
$\l_tmpb_tl = \fp_eval:n { \l_tmpa_tl }$
}

\NewDocumentCommand { \eq } { m } {
\typeset_eq:n { #1 }
}

\ExplSyntaxOff

\eq{ 1 + 2 * 3 }

\eq{ sin ( pi / 3 ) }

\eq{ cos ( pi / 4 ) }

\eq{ tan ( pi / 6 ) }

\end{document}


-