Best practice for printing and evaluating formulas with the minimal coding
AFAIK there is no such function available but I may be wrong. You could write your own parser that locally redefines the macros that print stuff to macros that wraps stuff in the respective functions. In the code below, I do that for \frac
and \sqrt
. This works in this case, also because you were kind enough to explicitly spell out multiplications and even used *
for them. Clearly, this "parser" is fragile, but if you really feel it is worthwhile you may add other functions like \sin
and so on.
\documentclass[border=5mm]{standalone}
\usepackage{pgf,mathtools,siunitx}
\begin{document}
\newcommand{\toprint}{\frac{-4+\sqrt{4^2-4*1*3}}{2}}
%\newcommand{\toevaluate}{(-4+sqrt(4^2-4*1*3))/2}
\newcommand{\DiaaParse}[1]{\begingroup\def\frac##1##2{((##1)/(##2))}%
\def\sqrt##1{sqrt(##1)}%
\edef\ret{#1}%
\pgfmathparse{\ret}\pgfmathprintnumber{\pgfmathresult}%
\endgroup}
%\pgfmathparse{\toevaluate}
The first root is evaluated by $x_1 = \toprint = \DiaaParse{\toprint}$
\end{document}
This version does not work with \SI
, also because I didn't understand where the units cm
come from, but this could be changed.
If you want the parser just to parse and to store the result in \pgfmathresult
, you could use
\documentclass[border=5mm]{standalone}
\usepackage{pgf,mathtools,siunitx}
\begin{document}
\newcommand{\toprint}{\frac{-4+\sqrt{4^2-4\times1\times 3}}{2}}
\newcommand{\DiaaParse}[1]{\begingroup\def\frac##1##2{((##1)/(##2))}%
\def\sqrt##1{sqrt(##1)}%
\def\cdot{*}%
\def\times{*}%
\def\exp##1{exp(##1)}%
\def\log##1{log(##1)}%
\def\ln##1{ln(##1)}%
\def\arcsin##1{asin(##1)}%
\def\cot##1{cot(##1)}%
\def\sin##1{sin(##1)}%
\def\sinh##1{sinh(##1)}%
\def\arccos##1{acos(##1)}%
\def\cot##1{cot(##1)}%
\def\cos##1{cos(##1)}%
\def\arctan##1{atan(##1)}%
\def\cot##1{cot(##1)}%
\def\tan##1{tan(##1)}%
\def\tanh##1{tanh(##1)}%
\def\arccot##1{acot(##1)}%
\def\cot##1{cot(##1)}%
\def\cot##1{cot(##1)}%
\edef\ret{#1}%
\pgfmathparse{\ret}%
\pgfmathsmuggle\pgfmathresult%
\endgroup}
The first root is evaluated by $x_1 = \toprint =\DiaaParse{\toprint}
\SI{\pgfmathresult}{\cm}$
\end{document}
As you see, this does work with \SI
and so on, simply because it wraps the additional parsing around \pgfmathparse
. This also defines the replacement rules for other commands, but I stress it is fragile. Please note that this requires a rather recent version of pgf (3.1.1 or higher, I think) which has \pgfmathsmuggle
in it. For older versions, you have to use other smuggling techniques, see the answers of this question for possible ways.
Overall this does something of the sort you are suggesting, but I stress it is fragile. What if a user wants to compute, say, \log_{7} 29
? Yes, one could extend the parser to deal with that as well, but this will be more effort. And then the next user wants \sqrt[3]{19}
. Also possible, but more efforts. And how about \log_{10} 3\frac{1}{4}
, how would the parser know that this is log(13/4)/log(7)
? Of course, if you use external programs, you can avoid duplication, e.g. Mathematica has TeXForm to convert the result of some module to not-so-nice but most times working (La)TeX code.
Some years ago, I had the same problem.
Since writing a robust parser is not a trivial exercise, I decided to not try it in TeX, but use Python (version 3.6 or later) instead.
The result was the TeXcalc module.
The input looks like this:
from texcalc import Calculation
c = Calculation()
c.add('rho_f', '1.62', 'g/cm^3', 'Fiber density')
c.add('rho_r', '1.2', 'g/cm^3', "Resin density")
c.add('v_f', '0.3', '-', 'Fiber volume fraction')
c.add('W_f', '450', 'g/m^2', "Area weight fibers", fmt=".0f")
c.add('t_f', 'W_f/(10000*rho_f)*10', 'mm')
c.add('t', 't_f/v_f', 'mm', "Laminate thickness")
c.add('t_r', 't-t_f', 'mm')
c.add('W_r', 't_f/10*(10000*rho_r)', 'g/m^2', "Area weight resin", fmt=".0f")
print(c)
It outputs an align*
environment (from the amsmath
package) and uses siunitx
to typeset the units. After processing with LaTeX, the output looks like this.
Adapted to the MWE on request
The following are the contents of mwe.py
from texcalc import Calculation
c = Calculation()
c.add('b', 4)
c.add('a', 1)
c.add('c', 3)
c.add('x1', '(-b+sqrt(b**2-4*a*c))/2', 'cm', 'first root')
c.add('x2', '(-b-sqrt(b**2-4*a*c))/2', 'cm', 'second root')
print(c)
Run this as python3 mwe.py > foo.tex
This is mwe.tex
:
\documentclass[preview=true]{standalone}
\usepackage{amsmath,siunitx}
\begin{document}
\input{foo.tex}
\end{document}
Run this with pdflatex mwe.tex
.
This results in:
The goal of TeXcalc is to clarify complicated calculations that have multiple steps, as shown in the first example. This to make it easier for others to follow.
So it cannot exactly match your MWE, since it doesn't produce in-line math. Although in this case, you could extract the necessary data from foo.tex
.