LaTeX 中的浮点计算?

LaTeX 中的浮点计算?

我正在寻找一种在 LaTeX 中进行最少浮点/整数计算的方法,目的不是为了编写包,而是为了生成实际文本。

下面是一个例子来说明。给定以下输入文本

 The experiment included running a battery of \bind{T}{21} tests
 on \bind{S}{13} subjects, for a total of \bind{V}{T*S} expected values.
 However, since \bind{F}{37} values were defective, our successful 
 measurement rate per subject was \use{100*round((V-F)/T,2)}\%

如果能转换成:

 The experiment included running a battery of $21$ tests
 on $13$ subjects, for a total of $273$ expected values.
 However, since $37$ values were defective, our successful 
 measurement rate per subject was $86$\%.

其中\bind{C}{expression}定义了一个新常量C,其值为expression,并返回C,而\use{C}仅返回 的值C。有什么建议吗?

我知道这个spreadtab包裹和这个问题:这个问题,但我还在寻找更多的东西。

答案1

如果您不介意使用 luatex,那么您可以让 lua 进行计算。我使用 ConTeXt,但我相信luacodeLaTeX 中的包提供了类似的功能。

\startusercode
  round = global.math.round 
\stopusercode

\def\bind#1#2%
    {\usercode{#1 = #2}\use{#1}}

\def\use#1%
    {\usercode{global.context(#1)}}

\starttext
 The experiment included running a battery of \bind{T}{21.0} tests
 on \bind{S}{13} subjects, for a total of \bind{V}{T*S} expected values.
 However, since \bind{F}{37} values were defective, our successful 
 measurement rate per subject was \use{100*round((V-F)/T,2)}\%
\stoptext

我使用usercode而是luacode为了使我的定义(T=21等)不污染全局命名空间。

编辑:如果希望结果为数学模式,请在定义中更改global.context(...)global.context.math(...)\use

答案2

另一个执行浮点计算的包是l3fp。此包(目前)不允许用户定义新变量(但它支持,例如,因此原则上扩展它以支持用户定义变量应该不太难)。一种解决方法是遍历表达式并将所有变量、等pi替换为内部变量、等,该变量保存相应的值。TV\l__my_T_fp\l__my_V_fp

这是通过循环宏完成的\__my_use:N,它一次读取一个字符。如果它是结束标记\q_recursion_tail,那么我们就到达了表达式的末尾,因此跳到\q_recursion_stop(完成\quark_if_recursion_tail_stop:n)退出循环。如果变量\l__my_#1_fp已定义,则使用它,否则将字符本身留给函数l3fp接收。然后通过\__my_use:N再次调用进行递归。

\my_set:nn函数确保\l__my_#1_fp通过 定义\fp_zero_new:c,然后设置其值。

\documentclass{article}
\usepackage{expl3, xparse}
\ExplSyntaxOn
\cs_new:Npn \__my_use:N #1
  {
    \quark_if_recursion_tail_stop:n {#1}
    \cs_if_exist_use:cF { l__my_#1_fp } {#1}
    \__my_use:N
  }
\cs_new:Npn \my_use:n #1
  { \fp_eval:n { \__my_use:N #1 \q_recursion_tail \q_recursion_stop } }
\cs_new_protected:Npn \my_set:nn #1#2
  {
    \fp_zero_new:c { l__my_#1_fp }
    \fp_set:cn { l__my_#1_fp } { \my_use:n {#2} }
  }
\NewDocumentCommand {\bind} { m m } { \my_set:nn {#1} {#2} \my_use:n {#1} }
\NewDocumentCommand {\use} { m } { \my_use:n {#1} }
\ExplSyntaxOff
\begin{document}
 The experiment included running a battery of \bind{T}{21} tests
 on \bind{S}{13} subjects, for a total of \bind{V}{T*S} expected values.
 However, since \bind{F}{37} values were defective, our successful
 measurement rate per subject was \use{100*round((V-F)/V,2)}\%
\end{document}

我还修复了最后一个公式,即(V-F)/T

答案3

我已经广泛使用fp来完成这类工作。下面是一些函数的最小版本,可以将温度单位从一个系统转换为另一个系统。此站点上有很多使用该fp包的示例。代码siunitx也使用该包进行格式化。

例如,要将华氏度转换为摄氏度,请输入\Ftoc{32.999}。这是一个简单的例子。

\documentclass{article}
\usepackage{fp}
\usepackage{siunitx}
\gdef\numdec{3}

\begin{document}
%\SetConversion{C}{K}{273.15}
\def\CtoK#1{\FPadd\result{#1}{273.15}%
\FPround\result{\result}{2}%
\sisetup{%
fixed-exponent = 2,
scientific-notation = false}
 \num{\result}}


%% Convert Centigrate to Fahreneit
\def\CtoF#1{\FPdiv\resulta{9}{5}%
\FPmul\resultb{\resulta}{#1}%
\FPadd\resultc{\resultb}{32}%
\FPround\resultc{\resultc}{3}%
 \num{\resultc}%
\sisetup{%
fixed-exponent = 0,
scientific-notation = false}
}

%% Convert Fahreneit to Centigrade
\def\FtoC#1{\FPdiv\resulta{5}{9}%
\FPsub\resultb{#1}{32}%
\FPmul\resultc{\resultb}{\resulta}%
\FPround\resultc{\resultc}{\numdec}%
\sisetup{%
fixed-exponent = 0,
scientific-notation = false}
\num{\resultc}%
}

%% Convert Fahreneit to Rankine
\def\FtoRa#1{\FPmul\result{#1}{9}%
\FPdiv\result{\result}{5}%
\FPround\result{\result}{\numdec}%
\result%
}

%% Convert Kelvin to Rankine
\def\KtoRa#1{\FPadd\result{#1}{459.67}%
\FPround\result{\result}{\numdec}\result}

%% Convert Rankine to Celcius
\def\RtoC#1{\FPsub\result{#1}{459.67}% to fahreneit
\FtoC{\result}}


\FtoC{32.999}

\end{document}

答案4

为了多样化,这里提供了一个基于 LuaLaTeX 的解决方案。它提供了两个 LaTeX 宏:\bind\use。此外,由于 Lua 没有提供内置round函数,因此它提供了 的实现round,供在\use指令中使用。

在此处输入图片描述

% !TEX TS-program = lualatex
\documentclass{article}

%% The LaTeX macros "\bind" and "\use" invoke "\directlua{...}"
%% to perform their task(s).
\newcommand\bind[2]{\directlua{#1=#2;tex.sprint(#1)}}
\newcommand\use[1]{\directlua{tex.sprint(#1)}}

%% Define two auxiliary functions: "round2int" and "round"
\directlua{%
   function round2int ( x )
      return x>=0 and math.floor(x+0.5) or math.ceil(x-0.5)
   end
   function round ( num , digits )
      return round2int ( num * 10^digits ) / 10^digits
   end
}

\begin{document}
The experiment included running a battery of \bind{T}{21} tests on
\bind{S}{13} subjects, for a total of \bind{V}{T*S} expected values.
However, since \bind{F}{37} values were defective, our successful 
measurement rate per subject was \use{100*round((V-F)/V,2)}\%. More 
precisely, the successful measurement rate per subject was 
\use{100*round((V-F)/V,4)}\%.
\end{document}

相关内容