# Autocalculate result in math-mode

Are there any available programs/software/etc. that allow you to autocalculate and then autocomplete TeX equations? It would be great if for example, I were doing really long messy equations like

120 000 \, inches \times \frac{1 \, mile}{63360 \, inches} =


and the program could just fill in the blank with

1.89 \, miles

-
I don't think there is anything available that does exactly what you want. There is a large amount of math software out there, from Mathematica, Maple, Sympy or the math library from PGF that can do the calculation and output to TeX but parsing TeX equations with units as text in between will be a bit difficult. –  Alexander Jan 24 '13 at 16:51
There are lot's of ways to calculate things. A few are mentioned in the answers to “square root of number in counter –  clemens Jan 24 '13 at 16:51
1st look on package fp. I've make something like "electronic tables" with it. –  Eddy_Em Jan 24 '13 at 16:54
You really shouldn't write units like that in math mode. Either use \text{} or, better yet, have a look at siunitx. It won't do anything bad to your hard drive when you feed it miles and inches. –  Christian Jan 24 '13 at 19:44
May be \pgfmathparse, \pgfmathresult, and similars from pgf would work well. I don't know them enough to answer. –  Manuel Jan 24 '13 at 23:17

Here's an approach based on my pythontex package, which provides access to SymPy. I've written some code that takes an expression written with siunitx, converts it to SymPy format (if it's not too complex and doesn't break the regular expressions), and then calculates the result. The SymPy code is accessed with a macro I've called \autocalc, which takes two arguments: an expression written with siunitx, and the desired units for the answer (also written with siunitx). This won't handle everything without some additional regex work, but it should handle most one-line unit conversions.

\documentclass{article}

\usepackage{pythontex}
\usepackage[per-mode=fraction]{siunitx}
% Define some English units
\DeclareSIUnit\inch{in}
\DeclareSIUnit\inches{in}
\DeclareSIUnit\ft{ft}
\DeclareSIUnit\foot{ft}
\DeclareSIUnit\feet{ft}
\DeclareSIUnit\mi{mi}
\DeclareSIUnit\mile{mi}
\DeclareSIUnit\miles{mi}

\begin{sympycode}
from sympy.physics.units import *
import re

def process_units(units):
''' Take units in siunitx form, and convert to SymPy format '''
# Take care of powers
units = units.replace(r'\squared', '**2')
units = re.sub(r'\\square(\$a-z]+)', r'\1**2', units) units = units.replace(r'\cubed', '**3') units = re.sub(r'\\cubic(\\[a-z]+)', r'\1**3', units) # Take care of \per units = re.sub(r'\\per(\\[a-z]+\**\d*)', r'/(\1)', units) # Add in multiplication as needed units = re.sub(r'($$*\\[a-z]+(?:\*\*\d+)*$$*)(\\[a-z]+)', r'\1*\2', units) units = re.sub(r'($$*\\[a-z]+(?:\*\*\d+)*$$*)(\\[a-z]+)', r'\1*\2', units) # Finally, remove backslashes units = units.replace('\\', '') return units def process_SI(matchobj): ''' Take an \SI macro, and convert it to SymPy form ''' num, units = matchobj.groups() units = process_units(units) result = num + '*' + units return result def calc_SI_expression(expr, final_units): ''' Turn a series of siunitx expressions into SymPy form, perform the calculation, and return the answer in the desired units ''' # Get rid of spaces in code from TeX expr = expr.replace(' ', '') final_units = final_units.replace(' ', '') # Start assembling the final result result = expr + ' = ' # Take care of multiplication and \left and \right expr = expr.replace('^', '**') expr = expr.replace(r'\left', '').replace(r'\right', '') expr = expr.replace('\\times', '*') # Convert all \SI macros to SymPy form expr = re.sub(r'\\SI\{(.+?)\}\{(.+?)\}', process_SI, expr) expr = re.sub(r'\\frac\{(.+?)\}\{(.+?)\}', r'(\1)/(\2)', expr) # Evaluate the string that is now in SymPy form expr = eval(expr + '/(' + process_units(final_units) + ')') # Round the result to a desired number of places expr = round(float(expr), 6) # Return original equation plus calculated result return result + '\SI{{{0}}}{{{1}}}'.format(expr, final_units) \end{sympycode} % Define a shortcut for accessing the Python function \newcommand{\autocalc}[2]{\sympy{calc_SI_expression(r"#1", r"#2")}} \begin{document} \[ \autocalc{ \SI{120000}{\inches} \times \frac{\SI{1}{\mile}}{\SI{63360}{\inches}} }{\miles}$

$\autocalc{ \SI{2}{\square\feet\per\second} \times \left( \frac{\SI{12}{\inches}}{\SI{1}{\foot}} \right)^2 \times \frac{\SI{3600}{\s}}{\SI{1}{\hour}} }{\square\inches\per\hour}$

\end{document}

-

You could use sage (sagetex) to do this.

%!TEX TS-program = sage
\documentclass{article}
\usepackage{sagetex}
\usepackage{amsmath}
\begin{document}
120000\, inches $\times \frac{1 \text{ mile}}{63360 \text{ inches}}$\,=$\sage{120000*1/63000}$\,miles.
\end{document}


-

You are not using the full power of TeX if you want to use it as described. TeX offers on the fly definitions using \csname...\endcsname which you can leverage both for typesetting as well as automatic calculations. For example if you are using the TeX to calculate conversions as per your example between units.

First define a way to set the conversion parameters with a macro:

   \SetConversion{ft^2}{m^2}{0.09290304}


and then use this to typeset the result:

   \convert{10.35}{ft^2}{m^2}


The macro name is defined as \ft^2m^2 using a \csname..\endcsname construct. By defining the macro appropriately we can also automate the reverse conversion i.e., \m^2ft^2.

A somewhat longish example:

\documentclass{minimal}
\usepackage{fp,xcolor,xspace,amsmath}

\makeatletter

%% globally set the numbers of decimals
\xdef\NumberDecimals{3}

\def\SetInBetween#1{\def\between{#1}}
\SetInBetween{\text{ equals }}

%% Temporary stores for real numbers for conversions
%% The first one just stores the multiplication number
\def\conversionfactora#1{%
\gdef\ConversionFactor{#1}}

%% The second one stores the inverse of this for two way
%% conversions

\def\inverseconversionfactor#1{
\gdef\InverseConversionFactor##1{\FPdiv\invert{1}{##1}\invert}
\InverseConversionFactor{#1}%
}

%% Creates all the macros for the conversion units
%% Then defines the relevant factors
\def\SetConversion#1#2#3{%
\expandafter\def\csname#1#2\endcsname{#3}%Define one way
\FPdiv\invert{1}{#3}
\expandafter\def\csname#2#1\endcsname{\invert}
}

%% helper macro to typeset the
%% units. If a formatting macro exists for the symbols
%% we use them, else we use the siunitx package commands
%%
\def\TypesetUnits#1#2{
\ifcsname#2\endcsname%
{#1 {\csname#2\endcsname}}
\else%
{#1 {#2}}%
\fi}
%% Define a store for the numbers
%% inUnitsValue defines the input value
\gdef\inUnitsValue{}
\gdef\outUnitsValue{}

%
%
%% The \convert is a convenience value
%% provided the conversion value has been set it will create
%% the conversion
\global\def\convert#1#2#3{%
\TypesetUnits{#1}{#2}\between%
%
%% We first test if a conversion factor formula has been
%% defined or is simply a multiplier
%% a conversion formula is of the form CtoF i.e centigrate
%% to Fahreneit
%% this handles pre-defined macros such as \degtoF
\ifcsname#2to#3\endcsname%
\expandafter\csname#2to#3\endcsname{#1}%
\csname#3\endcsname%typesets units
\else
\def\conversion@factor{\csname#2#3\endcsname}
%multiply value in by conversion factor
\FPmul\tempi{#1}{\conversion@factor}%
\FPround\temp{\tempi}{\NumberDecimals}%format units
\expandafter\TypesetUnits{\temp}{#3}%
\global\let\outUnitsValue\temp%stores raw output
\def\arg@i{#1}
\global\let\inUnitsValue\arg@i% stores raw input
\fi
}

\makeatother

\begin{document}
\parindent0pt

\SetConversion{ft^2}{m^2}{0.09290304}
\SetConversion{pous}{mm}{296}
\SetConversion{pous}{inch}{11.6}
\SetConversion{pous}{daktyloi}{16}

$$\convert{10.35}{ft^2}{m^2}$$

Perhaps one of the most common of all was the stadion, which was equal to 600 podes.

The most famous of all calculations using stadia was that of Eratosthenes who measured the circumference of the earth. Based on the interpretation of the length of the stadion, being either the Egyptian at 157.5 meters or the Greek which was 185 meters his calculation was fairly accurate.
Eratosthenes calculation of the circumference of the earth:

or Egyptian

This would give the radius of the earth as:

\SetConversion{m}{km}{0.001}

This can be compared to the mean earth radius of 6371 km


Code can be integrated with siunitx quite easily, avoided it in the example for simplicity. Code also illustrates the use of the fp package.

-
Not bad at all, but for this you'd need to set up lots of \SetConversion commands with individual factors, right? –  Hendrik Vogt Jan 25 '13 at 7:35
@HendrikVogt Yes correct, pretty much like setting up a conversion table. But you can use them 100s of times. It is not a calculator. If you just want calculations on the fly one can use the fp, as I calculateed the radius of the earth. One can also create a general utility factor, where you provide the conversion factor and typesets immediately. Wrap \SetConversion and convert in one macro. –  Yiannis Lazarides Jan 25 '13 at 8:19

Here is one of the possible ways I pointed to in a comment:

\documentclass{article}
\usepackage{expl3,xparse}

\ExplSyntaxOn
% \calculate[<places>]{<fp expr>}
% #1: number of places to round to (optional, default 4)
% #2: floating point expression as described in interface3.pdf
%     section 9, see http://texdoc.net/pkg/interface3
%
% internal command:
\cs_new:Npn \raindrop_calculate:nn #1#2
{ \fp_eval:n { round( #2 , #1 ) } }
% document level:
\NewDocumentCommand \calculate { O{4}m }
{ \raindrop_calculate:nn { #1 } { #2 } }
\ExplSyntaxOff

% formatting of units (probably better: package siunitx'):
\usepackage{amsmath}
\newcommand*\unit[1]{\text{#1}}

\begin{document}

$120 000\,\unit{inches} \times \frac{ 1\,\unit{mile} }{ 63360\,\unit{inches} } = \calculate{ 120000 / 63360 }\,\unit{miles}$

\end{document}


-

For simple calculations you can also use LuaTeX.

Here is an example in ConTeXt:

% Define miles as a unit
\registerunit[unit][mile=mile]

\unexpanded\def\InchesToMiles#1%
{\m{\unit{#1 inch} \times
\frac {\unit{1 mile}} {\unit {63360 inch}}
= \ctxlua{context.unit(string.format("\letterpercent 0.3f mile", #1/63360))}}}

\starttext
\InchesToMiles{120000}
\stoptext
`

which gives

-