# [Tex/LaTex] Autocalculate result in math-mode

calculationsmath-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


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}