使用 LuaTeX 或类似程序计算公式的值而不重复

使用 LuaTeX 或类似程序计算公式的值而不重复

如果我在 LaTeX 中有一个数值方程(即没有未知数),是否可以一次性排版并计算该方程?

显示展开形式和计算形式的方程

我知道使用 LuaTeX 嵌入 Lua 代码可以相对轻松地完成计算,但这需要重写方程式。解决方案还必须处理非常小和非常大的数字,因此我认为这超出了普通 TeX 的范围。

在 LaTeX 中定义一个公式,然后必须以线性格式再次写入它以计算其值,这看起来很愚蠢。

提前致谢。

答案1

由于@marmot 和@Mico 的两个很好的答案根本没有解决主要查询(只编码一次并获取排版和值)(参见@JosephWright 的回答),我可以自由地添加一个答案,不是解决请求,而是用进行计算xfp

但请参阅底部的更新\printandeval

\documentclass{article}
\usepackage[fleqn]{amsmath}
\usepackage{xfp}
\usepackage{siunitx}
\begin{document}
\begin{equation*}
  N = \frac{19.32\times1\times10^6\times6.023\times10^{23}}{197}
  =\num[scientific-notation=true,
        round-mode=figures,
        round-precision=4]{\fpeval{19.32*1*10^6*6.023*10^23/197}}
\end{equation*}
\end{document}

在此处输入图片描述

我不知道如何指示\fpeval以科学计数法(给定位数)输出,但是选项\num可以帮上忙。

我还会提到xintexpr(因为我是它的作者),尽管我仍然需要向其中添加数学函数(sqrt目前只有可用)。现在,它的语法会导致解析其参数\xintthefloatexpr...\relax的方式出现问题。因为使用括号,所以siunitx \num没有遇到这样的问题。所以让我们添加一个用户界面宏来使用括号,这很开心。\fpeval\fpeval\num

\documentclass{article}
\usepackage[fleqn]{amsmath}
\usepackage{xintexpr}
% make \num of siunitx happy, let xintexpr do the rounding to 4 digits
% of float precision (after having computed with 16 digits of
% precision, per default)
% #1 = final precision for printing, #2 = expression to evaluate
\newcommand\floatround[2]{\xintthefloatexpr [#1]#2\relax}
\usepackage{siunitx}
\begin{document}
\begin{equation*}
  N = \frac{19.32\times1\times10^6\times6.023\times10^{23}}{197}
  =\num{\floatround{4}{19.32*1*10^6*6.023*10^23/197}}
% one can also use ** in place of ^ for powers
\end{equation*}
\end{document}

在此处输入图片描述

最后打包numprint有很多建议根据文档语言打印数字。并且其\numprint宏(或\np与包选项一起np)将直接接受\xintthefloatexpr括号内的内容,而与\numsiunitx 相反。

\documentclass[english]{article}
\usepackage{babel}
\usepackage[fleqn]{amsmath}
\usepackage{xintexpr}
\usepackage[np, autolanguage]{numprint}
\begin{document}
\begin{equation*}
  N = \frac{19.32\times1\times10^6\times6.023\times10^{23}}{197}
  =\np{\xintthefloatexpr [4] 19.32*1*10^6*6.023*10^23/197\relax}
\end{equation*}
\end{document}

在此处输入图片描述


在这里考虑的简单示例中,可以这样做:

\documentclass[english]{article}
\usepackage{babel}
\usepackage[fleqn]{amsmath}
\usepackage{xintexpr}
\usepackage[np, autolanguage]{numprint}

\newcommand\printandeval[1]{#1=\begingroup
    \def\frac##1##2{(##1)/(##2)}%
    \def\times{*}%
    % etc...
    \edef\x{{\xintthefloatexpr[4]#1\relax}}%
    \expandafter\endgroup\expandafter\np\x
}

% (in the above we need to re-enact standard meaning of things
%  such as \times, before \np does the typesetting of the value,
%  this is the reason for the `\expandafter` chain.

\begin{document}
\begin{equation*}
  N = \printandeval{\frac{19.32\times1\times10^6\times6.023\times10^{23}}{197}}
\end{equation*}
\end{document}

在此处输入图片描述

我并不试图在这里提供一个完全通用的定义,但在实践中,添加一些重新定义将涵盖许多测试用例,可能足以满足实际使用。

请注意,排版输入中的括号在评估之前不必用圆括号替换(参见10^{23}

以下是带xfp+ 的情况siunitx

\documentclass{article}
\usepackage[fleqn]{amsmath}
\usepackage{xfp}
\usepackage{siunitx}
\newcommand\printandeval[1]{#1=\begingroup
    \def\frac##1##2{(##1)/(##2)}%
    \def\times{*}%
    % etc...
    \edef\x{[scientific-notation=true,
             round-mode=figures,
             round-precision=4]{\fpeval{#1}}}%
    \expandafter\endgroup\expandafter\num\x
}

\begin{document}
\begin{equation*}
  N = \printandeval{\frac{19.32\times1\times10^6\times6.023\times10^{23}}{197}}
\end{equation*}
\end{document}

相同的输出。

上面的代码可以稍微提高效率

\edef\x{\endgroup\noexpand\np{\xintthefloatexpr[4]#1\relax}}% \x

在这种numprint+xintexpr情况下

\edef\x{\endgroup\num[scientific-notation=true, round-mode=figures, round-precision=4]{\fpeval{#1}}}% \x

在这种siunitx+xfp情况下。

感谢 @egreg 追踪\expandafter并指出,\num\protected让我有机会在这次编辑中发现标记多行代码的新方法......(我在 github 上太活跃了)

答案2

只要表达式不是太复杂,我们就可以使用 LaTeX3 FPU 来完成这项工作。我采用了一种方法,将输入“重写”为适当的语法:也可以对其他人给出的基于 Lua 的答案这样做。

\documentclass{article}
\usepackage{siunitx,xparse}
\ExplSyntaxOn
\NewDocumentCommand { \printandcalc } { m }
  {
    #1 =
    \group_begin:
      \tl_set:Nn \l_tmpa_tl {#1}
      \cs_set:Npn \frac ##1##2 {##1/(##2)}
      \cs_set:Npn \times { * }
      \cs_set:Npx \__cs_tmp:w ##1 { \token_to_str:N ^ (##1) }
      \char_set_active_eq:NN ^ \__cs_tmp:w
      \tl_set_rescan:Nnx \l_tmpa_tl { \char_set_catcode_active:n { `\^ } }
        { \l_tmpa_tl }
      \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl }
    \exp_args:NNNV \group_end:
    \tl_set:Nn \l_tmpa_tl \l_tmpa_tl
    \num [scientific-notation = true, round-mode = places]
      { \fp_eval:n { \l_tmpa_tl } }
}
\begin{document}
\[
N = \printandcalc{\frac{19.32\times1\times10^6\times6.023\times10^{23}}{197}}
\]
\end{document}

答案3

欢迎来到 TeX.SE!这里有关于如何LaTeX 中的严肃计算。我的回答基于这个答案最好是一个起点,表明确实有可能按照这样的思路做某事。

\documentclass{article}
\usepackage[fleqn]{amsmath}
\usepackage{luacode}
% from https://tex.stackexchange.com/a/294465/121799
\def\luaprint#1{\directlua{tex.print(#1)}}
\begin{document}
\begin{equation*}
  N = \frac{6.022\cdot10^{23}}{1.2\cdot10^{19}}
  =\luaprint{(1.932*10^6)*6.022*10^(23)/(197)}
\end{equation*}
\end{document}

在此处输入图片描述

还要注意,在 LateX 中有多种打印这些数字的可能性。不幸的是,我对此了解不多,luacode但我知道的是 pgfmanual 的第 92 节列出了在 Ti 中执行此操作的几种可能性Z/pgf。

答案4

这个答案仅仅是@marmot 的回答。它使用(a)环境luacode以允许使用“魔法”字符的方式定义 Lua 函数%,以及(b)包\num的宏siunitx,以美化 Lua 计算的输出。

这绝对是可能的创建一个预处理器类型的函数,用于捕获和修改\frac{...}{...}\log\sin\pi等的所有实例,以便 Lua 可以解析代码。(它必须处于预处理器阶段,这样 TeX 才不会尝试对\frac^等进行操作。)一个非常重要的考虑因素是 TeX 的分组字符{}必须替换为()。除非您需要在文档中执行大量公式评估,否则“手动”执行简化和调整几乎肯定会快得多。

在此处输入图片描述

\documentclass{article}
\usepackage{luacode,siunitx}
%% Lua-side code:
\begin{luacode}
function luaprint ( n )
  return tex.sprint ( string.format ( "%.3e" , n ) )
end
\end{luacode}
%% LaTeX-side code:
\def\luaprint#1{\num{\directlua{luaprint(#1)}}}

\begin{document}
\[
N = \frac{19.32\times1\times10^6\times6.023\times10^{23}}{197}
    =\luaprint{(19.32*1*10^6*6.023*10^(23))/197}
\]
\end{document}

相关内容