是否有任何 (开源) 解决方案可以将数学表达式从类似 C 的表达式语法转换为 LaTeX?当我说“解决方案”时,我的意思是从 LaTeX 外部 (即:进行转换并输出 LaTeX 语法的外部程序) 或从 LaTeX 内部 (即:某些采用类似 C 的数学并即时以公式格式显示的软件包)。
举个例子,我要求从 转换3*c/(a+2)
为\frac{3 c}{a + 2}
,是的,我知道转换不是唯一的,因为这3 \frac{c}{a + 2}
也是合法的转换。
我知道一些开源 CAS 包,例如 Maxima 或 SymPy 可以做到这一点,但我想知道是否还有其他更简单、开销更低的解决方案,而不需要安装完整的 CAS 系统。
答案1
(我重写了代码,使其由三个独立的文件组成:生成屏幕截图的驱动程序 tex 文件;设置主用户宏的样式文件(由驱动程序文件加载),称为\prettymath
;以及执行实际工作的 lua 文件(通过dofile
指令从样式文件加载)。)
以下基于 LuaLaTeX 的解决方案不应被视为成熟的工具。目前,它主要是为了展示 Lua 的一些字符串函数在解决手头问题方面的实用性和多功能性。
它处理**
指数符号,删除单个实例,将选定的小写希腊字母(例如和)*
的罗马字母表示转换为其“原生”希腊字符字形,并以漂亮的方式打印积分表达式、选定的三字母 mathop 函数(、、和——扩展此列表应该很简单)以及平方根和分数。它可以处理嵌套分数和平方根。当然,这个列表远非完整。希望下面显示的代码是相当不言自明的,这样(我希望)处理其他情况不会太难。alpha
pi
sin
cos
tan
det
驱动文件:
% !TeX program = lualatex
% Test file to check out operation of 'cmath2latex' package
\documentclass{article}
\usepackage{cmath2latex}
% set up three test strings
\newcommand\mystringa{sqrt(3**(x)*(a*sin(exp(theta))
*cos(2*pi)) / (det (A)*tan(gamma)) ) }
\newcommand\mystringb{3*c/(a+2), 1/pi, pi/2, 2*pi/3, a/b,
x/(y+z), (x+y)/z, (a/b)/(c/d)}
\newcommand\mystringc{sqrt( sqrt(sqrt(256))), Integral
(sqrt((2**(y))/(y)) , y )}
\begin{document}
\everymath{\displaystyle} % just for this example
\verb&sqrt(3**(x)*(a*sin(exp(theta))*cos(2*pi)) / (det (A)*tan(gamma)) )&
\prettymath{\mystringa}
\bigskip
\verb&3*c/(a+2), 1/pi, pi/2, 2*pi/3, a/b, x/(y+z), (x+y)/z, (a/b)/(c/d)&
\prettymath{\mystringb}
\bigskip
\verb&sqrt( sqrt(sqrt(256))), Integral (sqrt((2**(y))/y) , y )&
\prettymath{\mystringc}
\end{document}
样式文件;我建议你将其命名为cmath2latex.sty
:
% !TeX program = lualatex
\ProvidesPackage{cmath2latex}[2017/01/09, version 0.01]
\usepackage{luacode} % for "\luastring" macro
\usepackage{amsmath} % for "\ensuremath" macro
%% Load the Lua code
\directlua{dofile("cmath2latex.lua")}
%% The LaTeX macro "\prettymath" calls the Lua function
%% "prettymath" and outputs the result in math mode
\newcommand\prettymath[1]{\ensuremath{\directlua{%
tex.sprint(prettymath(\luastring{#1}))}}}
包含 Lua 代码的文件;我建议您将其命名为“cmath2latex.lua”:
-- cmath2latex.lua
-- This file is loaded by cmath2latex.sty via a dofile call
-- "prettymath" is called by the "\prettymath" LaTeX macro
-- (which is defined in "prettymath.sty")
function prettymath ( s )
-- exponential notation
s = s:gsub ( "%*%*%s-(%b())" , do_exp )
-- multiplication: delete all single instances of "*"
s = s:gsub ( "%*" , "" )
-- integrals
s = s:gsub ( "Integral%s-(%b())", do_integral )
-- some Greek letters
s = s:gsub ( "alpha" , do_gr_letter )
s = s:gsub ( "beta" , do_gr_letter )
s = s:gsub ( "gamma" , do_gr_letter )
s = s:gsub ( "Gamma" , do_gr_letter )
s = s:gsub ( "delta" , do_gr_letter )
s = s:gsub ( "Delta" , do_gr_letter )
s = s:gsub ( "theta" , do_gr_letter )
s = s:gsub ( "pi" , do_gr_letter )
s = s:gsub ( "Pi" , do_gr_letter )
-- some pre-defined 3-letter operators w/ args in parens
s = s:gsub ( "(cos)%s-(%b())" , do_mathop )
s = s:gsub ( "(det)%s-(%b())" , do_mathop )
s = s:gsub ( "(exp)%s-(%b())" , do_mathop )
s = s:gsub ( "(lim)%s-(%b())" , do_mathop )
s = s:gsub ( "(sin)%s-(%b())" , do_mathop )
s = s:gsub ( "(tan)%s-(%b())" , do_mathop )
-- sqrt function
for i=1,3 do -- allow for nested sqrt expressions
s = s:gsub ( "sqrt%s-(%b())", do_sqrt )
end
-- fraction expressions
s = s:gsub ( "(%b())%s-/%s-(%b())" , do_frac_2parens )
s = s:gsub ( "([\\%w]+)%s-/%s-(%b())" , do_frac_1parens_numer )
s = s:gsub ( "(%b())%s-/%s-([\\%w]+)" , do_frac_1parens_denom )
s = s:gsub ( "([\\%w]+)%s-/%s-([\\%w]+)", "\\frac{%1}{%2}" )
-- Feel free to add more string.gsub ops as needed...
-- Return the modified string
return s
end -- end of 'prettymath' function
-- Finally, set up the helper Lua functions
function strip ( x ) -- remove first and last char of string "x"
return x:sub(2,-2)
end
function do_exp ( u )
return ( "^{" .. strip(u) .. "}" )
end
function do_gr_letter ( u )
return ( "\\"..u )
end
function do_mathop ( u , v )
return ( "\\" .. u .. v )
end
function do_integral ( u )
u = strip(u)
return ( "\\int\\! " .. u:gsub ( "^(.*),(.*)$" ,
"%1 \\,\\mathrm{d} %2" ) )
end
function do_sqrt ( u )
return ( "\\sqrt{" .. strip(u) .. "}" )
end
-- process expressions involving fractions
function do_frac_1parens_numer ( u , v )
return ( "\\frac{" .. u .. "}{" .. strip(v) .. "}" )
end
function do_frac_1parens_denom ( u , v )
return ( "\\frac{" .. strip(u) .. "}{" .. v .. "}" )
end
function do_frac_2parens ( u , v )
return ( "\\frac{" .. strip(u) .. "}{" .. strip(v) .."}" )
end