Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

share|improve this question
2  
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

6 Answers 6

up vote 6 down vote accepted

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).

enter image description here

\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.

share|improve this answer

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}
share|improve this answer
    
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.

share|improve this answer

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:

enter image description here

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}

\newcommand*{\AdjustInput}[1]{%
    \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}}%
    }{%
        \ensuremath{\AdjustInput{#2}=\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}
share|improve this answer
4  
As you see, I can use \ensuremath sometimes. :) –  egreg Nov 30 '11 at 0:15
1  
@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
    answer = tostring(input)
    answer = string.gsub(answer, "\%.", "{,}")
    calculation = "#2"
    calculation = string.gsub(calculation, "*", "\\cdot ")
    calculation = string.gsub(calculation, "\%.", "{,}")
    if check == "f" then
       tex.sprint("\\ensuremath{", answer, "}")
    else
       tex.sprint("\\ensuremath{", calculation, "=", answer, "}")
    end
}}
\begin{document}
\ca{1+2.2 - 5/2} \par
\ca[t]{3+1-2.34*3}
\end{document}

enter image description here

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
    answer = tostring(input)
    answer = string.gsub(answer, "\%.", "{,}")
    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
       tex.sprint("\\ensuremath{", answer, "}")
    else
       tex.sprint("\\ensuremath{", calculation, "=", answer, "}")
    end
}}
share|improve this answer

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}

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.