删除累计和 + 定义局部变量 + if

删除累计和 + 定义局部变量 + if

下面的代码是错误的,但它说明了我想要实现的目标。你会如何编写 g 命令?

\usepackage{xfp}
\newcommand{\f}[1]{
    \inteval{(#1 - \a) / (\b - \a)}
}
\newcommand{\g}[1]{
    f=\f{#1}
    if (f>h1)
       f = f-(h1-l1)
    if (f>h2)
       f = f-(h2-l2)
    f % meaning return f. My purpose is to return an integer not to type anything.
}

理想情况下,我会有一个 (l_i,h_i) 夫妇列表,其中 h_i>l_i,并且我会从 f 中删除所有 (h_i-l_i) ,其 h_i < f。

如果我只有几个,我可以手动编写它们。否则,我很乐意迭代列表或其他结构。

请建议尽可能简单的语法。这就是我欣赏 xfp 的原因。除了 \inteval 和 \fpeval 之外,其余的都是数学,就像我会写的那样。对于 Latex 新手来说,添加太多东西令人沮丧。

答案1

与其他编程语言不同,TeX 没有“返回值”的概念,因此编程通常要棘手得多(当然,也并非不可能)。

TeX 大致通过扩展和赋值来工作,在这里你可以使用其中任何一种。这里有一个通过扩展工作的版本(这意味着你可以将其用作\g其他函数或整数表达式的参数):

\newcommand{\f}[1]{%
  \inteval{(#1 - \a) / (\b - \a)}}

\newcommand{\g}[1]{%
  \expandafter\gaux\expandafter{\number\f{#1}}}
\newcommand{\gaux}[1]{%
  \ifnum#1>\hI
    \inteval{#1-(\hI-\lI)}%
  \else\ifnum #1>\hII
    \inteval{#1-(\hII-\lII)}%
  \fi\fi}

此处命令使用\g强制扩展,并将结果传递给。 然后使用 执行条件并返回 中的表达式。我使用而不是 ,因为您(通常)不能在命令名称中使用数字,其他变量也是如此。\f{#1}\number\gaux\gaux\ifnum\inteval\hIh1

这里有一个使用赋值的可能性。这意味着结果在中返回\freturn(您可以使用 编写结果\the\freturn),并且不能嵌套\g\g其自身或其他类似命令中:

\newcommand{\f}[1]{%
  \inteval{(#1 - \a) / (\b - \a)}}

\newcount\freturn
\newcommand{\g}[1]{%
  \freturn=\f{#1}
  \ifnum\freturn>\hI
    \freturn=\inteval{\freturn-(\hI-\lI)}
  \else\ifnum \freturn>\hII
    \freturn=\inteval{\freturn-(\hII-\lII)}
  \fi\fi}

这首先将 的输出存储\f{#1}在 中\freturn,然后用于\freturn计算条件,最后\freturn再次将输出存储在 中。请注意,在这种情况下\g,它本身不会将任何内容写入输出,您必须写入\g{<num>} \the\freturn

答案2

感谢您的帮助。

我整合了你的建议来得到这个工作示例:

\documentclass{article}
\def\maxX{100}
\def\fd{0}
\def\ld{100}
\def\lI{0}
\def\hI{10}
\def\lII{20}
\def\hII{30}
\usepackage{xfp}
\newcommand{\f}[1]{%
    \inteval{\maxX * (#1 - \fd) / (\ld - \fd)}
}
\newcount\xTemp
\newcommand{\g}[1]{%
  \expandafter\gaux\expandafter{\number\f{#1}}}
\newcommand{\gaux}[1]{%
  \xTemp=#1
  \ifnum#1>\inteval{\hI}
    \xTemp=\inteval{\xTemp-(\hI-\lI)}%
  \fi
  \ifnum #1>\inteval{\hII}
    \xTemp=\inteval{\xTemp-(\hII-\lII)}%
  \fi
}
\begin{document}
% below is just a way for me to see the results
\begin{tabular}{ r r }
    $x$ & $g(x)$ \\
    \hline
    0 & \g{0} \the\xTemp\\
    15 & \g{15} \the\xTemp\\
    35 & \g{35} \the\xTemp\\
    \hline
\end{tabular}
\end{document}

我现在将寻找一种方法来迭代这些(l_i,h_i)以重复相同的计算几次,而不必将它们全部写出来。

再次感谢你。

答案3

如果我正确理解了您的目标,那么您有一个子区间列表,并且您想使用所有子区间进行显示的计算。

\documentclass{article}

\ExplSyntaxOn

\int_const:Nn \c_filippo_a_int { 0 }   % fd
\int_const:Nn \c_filippo_b_int { 100 } % ld
\int_const:Nn \c_filippo_m_int { 100 } % maxX

\int_new:N \l__filippo_step_int

\seq_const_from_clist:Nn \c_filippo_l_seq {  0,20,40,60,80 } % l_i
\seq_const_from_clist:Nn \c_filippo_h_seq { 10,30,50,70,90 } % h_i

\cs_new:Nn \filippo_f:n
 {
  \int_eval:n
   {
    100 * ( #1 - \c_filippo_a_int ) / ( \c_filippo_b_int - \c_filippo_a_int )
   }
 }
\cs_generate_variant:Nn \filippo_f:n { e }

\cs_new:Nn \filippo_g:n
 {
  \__filippo_g:ee { \filippo_f:n { #1 } } { 0 }
 }

\cs_new:Nn \__filippo_g:nn
 {
  \int_compare:nTF { #2 < \seq_count:N \c_filippo_l_seq }
   {% do the comparison
    \int_compare:nTF { #1 > \seq_item:Nn \c_filippo_h_seq { #2 + 1 } }
     {
      \__filippo_g:ee
       {
        \int_eval:n
         {
          #1 -
          \seq_item:Nn \c_filippo_h_seq { #2 + 1 } +
          \seq_item:Nn \c_filippo_l_seq { #2 + 1 }
         }
       }
       { \int_eval:n { #2 + 1 } }
     }
     {
      \__filippo_g:ee { #1 } { \int_eval:n { #2 + 1 } }
     }
   }
   {% we've ended the recursion, return the value
    #1
   }
 }
\cs_generate_variant:Nn \__filippo_g:nn { ee }

\NewExpandableDocumentCommand{\g}{m}
 {
  \filippo_g:n { #1 }
 }

\ExplSyntaxOff

\begin{document}

\begin{tabular}{ r r }
    $x$ & $g(x)$ \\
    \hline
     0 & \g{0} \\
     1 & \g{1} \\
    10 & \g{10} \\
    12 & \g{12} \\
    15 & \g{15} \\
    35 & \g{35} \\
    \hline
\end{tabular}

\bigskip

\edef\test{\g{35}}
\texttt{\meaning\test}

\end{document}

该命令\g是完全可扩展的,如最后一行所示。

的第二个参数\__filippo_g:ee是递归的循环索引。该函数在新的输入上调用自身,直到子间隔列表完成,此时返回第一个参数,否则循环索引将递增。

在此处输入图片描述

相关内容