Is there a (hopefully simple) way to convert a mathematical TeX expression, such as \frac{\cos(x^2) - x}{x^2 + 1}, to expressions which you would use in a programming language? The outcome of the example should be (cos(x^2) - x)/(x^2 + 1).
4 Answers
It is of course possible it depends what tools you want to use and what subset of latex you want to support (you show an easy case, if the latex has fonts and colours or explicit spacing it gets harder). Wolfram alpha for example can compute with the expression exactly as given, in latex syntax.
https://www.wolframalpha.com/input/?i=%5Cfrac%7Bcos%28x%5E2%29+-+x%7D%7Bx%5E2+%2B+1%7D
It also works with cos corrected to \cos
https://www.wolframalpha.com/input/?i=%5Cfrac%7B%5Ccos%28x%5E2%29+-+x%7D%7Bx%5E2+%2B+1%7D
- 757,742
-
Take also a look at the Python package associated to WolframAlpha. Here is an article about it: https://www.geeksforgeeks.org/python-create-a-simple-assistant-using-wolfram-alpha-api/ . – projetmbc Apr 18 '21 at 19:52
(augmented the Lua code so that instances of \sqrt{...} are processed as well)
Here's a LuaLaTeX-based solution. It consists of a LaTeX utility macro called \latextocmath and two Lua functions -- latex2cmath and do_frac -- which perfom most of the work with the help of Lua's built-in string functions and pattern matching capabilities.
The argument of \latextocmath may contain line breaks. However, the argument of \latextocmath is not expanded before it is passed to the Lua function latex2cmath. Hence, if you define a LaTeX macro called, say, \mymacro, via \newcommand\mymacro{1+1}, then the output of \latextocmath{\mymacro} is the string mymacro, not 1+1. I trust this restriction won't be burdensome.
If the numerator and denominator terms of a \frac expression consist of a single letter or a number, the terms are not encased in parentheses. This should help reduce the amount of visual clutter in continued fractions as well as in simple expressions such as \frac{u}{v}.
This approach can obviously be extended in many ways, depending on the programming code conventions you wish to adhere to and the types of math expressions that need to be fixed. Of course, converting commutative diagrams into inline C-type code will be very, very tedious, to say the least.
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{amsmath} % for \cfrac, \dfrac, and \tfrac
\usepackage{luacode} % for 'luacode*' env. and '\luastringN' macro
\begin{luacode*}
function do_frac ( s ) -- convert \\frac notation to inline-math notation
return ( s:gsub ( "\\[cdt]?frac%s-(%b{})%s-(%b{})" , function ( x , y )
x = x:sub ( 2 , -2 ) -- strip off the curly braces
y = y:sub ( 2 , -2 )
if not (string.len(x)==1 or tonumber(x)) then x = "("..x..")" end
if not (string.len(y)==1 or tonumber(y)) then y = "("..y..")" end
return x.."/"..y
end ) )
end
function latex2cmath ( s )
s = s:gsub ( "\[,:;!]" , "" ) -- delete ',' ':' ';' and '!' substrings
s = s:gsub ( "\mkern..-mu" , "" ) -- delete math kerns
s = s:gsub ( "\[cl]?dots" , "..." ) -- (typographic) ellipses
s = s:gsub ( "\sqrt%s-(%b{})" , "sqrt(%1)" )
while s:find ( "\[cdt]?frac" ) do s = do_frac ( s ) end -- nested \frac-like terms
s = s:gsub ( "\(%a+)" , "%1" ) -- drop leading backslashes from \cos, \Delta, etc
s = s:gsub ( "%^" , "\textasciicircum " ) -- make carets visible
tex.sprint ( ( s:gsub ( "%s" , "" ) ) ) -- omit all whitespace
end
\end{luacode*}
%% The LaTeX utility macro:
\newcommand\latextocmath[1]{\texttt{\directlua{ latex2cmath ( \luastringN{#1} ) }}}
\begin{document}
\[
\frac {u}{v} \quad
\frac{ \sqrt { 2 } } {2} \quad
\frac {\cos (x^2) - x} {x^2 + 1} \quad
\dfrac{\dfrac{\alpha+\beta}{\Gamma+\Delta}}{\tfrac{3+4}{5+6}} \quad
1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{ 1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cdots}}}}}}}}
\]
\obeylines
\latextocmath{ \frac {u}{v} }
\latextocmath{ \frac{ \sqrt { 2 } } {2} }
\latextocmath{\frac {\cos (x^2) - x} {x^2 + 1}}
\latextocmath{ \dfrac{\dfrac{\alpha+\beta}{\Gamma+\Delta}}{\tfrac{3+4}{5+6}} }
\latextocmath{1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{ 1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1+\cdots}}}}}}}}}
\end{document}
- 506,678
-
The
forloop could be replaced by awhileone that callsdofracwhile a new string is obtained. – projetmbc Apr 18 '21 at 22:21 -
@projetmbc - Many thanks for the suggestion to replace the
forloop (with a predetermined number of repetitions) with awhileloop that operates as long as\\[cdt]?fracis found in the input strings. Will implement the idea right away. – Mico Apr 19 '21 at 00:34 -
-
@wipet -- Just insert the following line right before the
while ...line:s = s:gsub ( "{(.-)\\over%s*(.-)}" , "\\frac{%1}{%2}" ). That, or feel free to replicate thedo_fracfunction withdo_over... – Mico Apr 19 '21 at 17:35 -
Thanks for quick reply. But
\textocmath{ {{ 2 \over 2+1 }\over 3 } }hangs. – wipet Apr 19 '21 at 17:44 -
@wipet - I did answer your initial question correctly, didn't I? :-) [FWIW, I refuse to be drawn into the debate over whether
\over-type infix notation is better or worse than\fracnotation, as I have nothing original or new to say on this subject.] Incidentally,do_fracby design does not work on inputs such as\frac12or\frac23-- the Lua function's%b{}pattern match criterion requires the arguments to be enclosed in matching curly braces. Feel free to ask a new question about how one might write ado_overfunction that's equivalent todo_frac. – Mico Apr 19 '21 at 17:59
The Emacs calc-embedded mode can do the trick. assuming you are editing a LaTeX file containing
$ \frac {\cos (x ^ 2) - x} {x ^ 2 + 1} $
and the point (the cursor) on it, just type C-x * e to enter calc-embedded mode. Then type d N (display normal ) to display
$ (cos (x ^ 2) - x) / (x ^ 2 + 1) $
d L (displays LaTeX) to return to LaTeX syntax.
C-x * e to exit the calc-embedded mode and continue the LaTeX file editing.
Bonus
Note that calc-embedded is a nice feature for language syntaxes. Possible syntaxes include C, Fortran, Pascal, TeX, LaTeX, Yacas, Maxima, Giac, Maple, Mathematica, etc ...
calc-embedded also allows rapid entry of matrices in TeX or LaTeX syntax: you enter the matrix online in normal mode $[[a b c] [d e f]]$ and calc-embedded instantly converts to TeX or LaTeX mode active for the document (commas optional).
For example $ \ begin {pmatrix} a & b & c \\ d & e & f \ end {pmatrix} $ in LaTeX mode.
-
Interesting! I tried to find the source code of where this parsing from TeX syntax is done, and some of it seems to be in this file. – ShreevatsaR Apr 19 '21 at 01:14
I use Sympy for phrasing (and generating) Latex.
from sympy.parsing.latex import parse_latex
expr = parse_latex(r"\frac{\cos(x^2) - x}{x^2 + 1}")
print(expr) # Prints "(-x + cos(x**2))/(x**2 + 1)"
Bonus
from sympy import latex
print(latex(expr)) # Prints "\frac{- x + \cos{\left(x^{2} \right)}}{x^{2} + 1}"
Sympy has code generators that you can use to generate code in, C, Fortran, Javascript, Julia, Mathematica, Octave/Matlab, and Python (which it, unsurprisingly, has rich support for).
from sympy import ccode, fcode, jscode, julia_code, mathematica_code, octave_code
# C code
print(ccode(expr)) # (-x + cos(pow(x, 2)))/(pow(x, 2) + 1)
# Fortran
print(fcode(expr)) # (-x + cos(x**2))/(x**2 + 1)
# Javascript
print(jscode(expr)) # (-x + Math.cos(Math.pow(x, 2)))/(Math.pow(x, 2) + 1)
# Julia
print(julia_code(expr)) # (-x + cos(x.^2))./(x.^2 + 1)
# Mathematica
print(mathematica_code(expr)) # (-x + Cos[x^2])/(x^2 + 1)
# Octave/Matlab
print(octave_code(expr)) # (-x + cos(x.^2))./(x.^2 + 1)
# Python
print(expr) # (-x + cos(x**2))/(x**2 + 1)
# Or use lambdify to directly make a Numpy accelerated callable python function
Some notes on getting this setup, you need the antlr4-python3-runtime to use this feature. If you get an error like; ANTLR runtime and generated code versions disagree: 4.9.2!=4.7.2, you need to install the version of the ANTLR runtime that matches the version that Sympy expects, i.e. pip install antlr4-python3-runtime==4.7.2.
- 277


(a*x+b)*x+cis both more accurate and faster thana*x^2+b*x+c.. – John Kormylo Apr 19 '21 at 03:10