bigintcalc:使用结果进行进一步计算

bigintcalc:使用结果进行进一步计算

我有一个\newcommand计算
在此处输入图片描述 对于预定义变量 在此处输入图片描述

提示:我用它bigintcalc.sty来表示巨大的数字;并pgfmath定义变量(也许还​​有其他计算)。

我希望结果为,像\Prod{3},这样我就可以做进一步的计算;例如\Prod{3}+1

\bigintcalc但是,如果我将 \Prod{3} 放在另一个中,例如\bigintcalcAdd{1}{\Prod{3}},这可能不起作用。

我需要做什么?

在此处输入图片描述

\documentclass[]{article}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{math}% for numbered Variables \x{1}, \x{2}, .... 
\usepackage{bigintcalc}% for big numbers  (e.g. 9^66)

\begin{document}
\section*{Define Variables}
\tikzmath{
int \i;
\i=0;
for \xValue in {2, 3, 7, 42, 1806}{%
      \i=\numexpr\i+1\relax;
      \x{\i}=\xValue;  
};%  %%
}

x(1)= \x{1}, ~~~  x(2)= \x{2}, ~~~  x(3)= \x{3}, ~~~  x(4)= \x{4}, ~~~  x(5)= \x{5}


\section*{bigintcalc-Product as command -- works}
\newcommand\Prod[1]{%
\def\N{#1}%
\def\p{1}%
 \foreach \k in {1,...,\N}{%%
  \xdef\p{\bigintcalcMul{\p}{\x{\k}}}%
}%%
\p}%

$\text{Prod(3)} =  \Prod{3} 
  = x(1) \times x(2) \times x(3) = 2 \times 3 \times 7$


\section*{Using the result for other calculations-- works not}
\text{Prod(3)} + 1 = %\bigintcalcAdd{1}{\Prod{3}}
\end{document}

答案1

您的宏\Prod被定义为将结果存储在宏中\p。因此,的结果\Prod可以在其他计算中访问,如下所示\p

或者,您可以定义一个完全可扩展的宏机制
\MyProd{⟨array-macro⟩}{⟨lowest array index⟩}{⟨highest array index⟩}
,通过触发两个扩展步骤来提供计算结果。扩展可以通过\expanded{..}/完成\expanded{\unexpanded{..}..},但对于以下示例,我决定使用它\romannumeral来触发扩展。

\documentclass[]{article}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{math}% for numbered Variables \x{1}, \x{2}, .... 
\usepackage{bigintcalc}% for big numbers  (e.g. 9^66)

\newcommand\Prod[1]{%
  \def\p{1}%
  \foreach \k in {1,...,#1}{%
    \xdef\p{\bigintcalcMul{\p}{\x{\k}}}%
  }%
  \p
}%

\makeatletter
\newcommand\PassFirstToSecond[2]{#2{#1}}%
\@ifdefinable\stopromannumeral{\chardef\stopromannumeral`\^^00 }%
\newcommand\MyProd[3]{%
  % #1 - array-macro; #2 - lowest array index;  #3 - highest array index; 
  \romannumeral
  \expandafter\MyProdLoop
  \expandafter{\the\numexpr(#3)\relax}{#1}{1}{#2}{}%
}%
\newcommand\MyProdLoop[5]{%
  % #1 - highest array index; #2 - array-macro; #3 - 1 or empty ; 
  % #4 - current array index;  #5 - result currently calculated so far; 
  \ifnum\numexpr(#4)\relax>\numexpr(#1)\relax
  \expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi
  {%
    % manual of bigintcalc says: "The macros are fully expandable,
    % exactly two expansion steps generate the result."
    \expandafter\expandafter\expandafter\PassFirstToSecond
    \expandafter\expandafter\expandafter{%
      \bigintcalcMul{#3#5}{#2{#4}}%
    }{%
      \expandafter\PassFirstToSecond\expandafter{%
        \the\numexpr(#4)+1\relax
      }{%
        \MyProdLoop{#1}{#2}{}%
      }%
    }%
  }{\stopromannumeral#5}%
}
\makeatother

\begin{document}

\section*{Define Variables}
\tikzmath{%
  int \i;
  \i=0;
  for \xValue in {2, 3, 7, 42, 1806}{%
    \i=\numexpr\i+1\relax;
    \x{\i}=\xValue;  
  };%
}%
\(x(1) = \x{1}\), \hfill
\(x(2) = \x{2}\), \hfill
\(x(3) = \x{3}\), \hfill
\(x(4) = \x{4}\), \hfill
\(x(5) = \x{5}\)%

\section*{bigintcalc-Product as command -- works}

\(\text{Prod(3)} =  \Prod{3} = \p = x(1) \times x(2) \times x(3) = 2 \times 3 \times 7\)

\section*{Using the result stored as \texttt{\string\p} for other calculations}
% The result of \Prod{3} is in \p, so use \p:
\(\text{Prod(3)} + 1 = \bigintcalcAdd{1}{\p}\)

\section*{Expandably calculating the result within other calculations by means of \texttt{\string\MyProd}}
% Use the expandable variant:
\(\text{Prod(3)} + 1 = \bigintcalcAdd{1}{\MyProd{\x}{1}{3}}\)

\end{document}

在此处输入图片描述

如果使用了 TeX 引擎并且\unexpanded\expanded可用,则可以定义\MyProd,例如,如下所示:

\makeatletter
\newcommand\MyProd[3]{%
  % #1 - array-macro; #2 - lowest array index;  #3 - highest array index; 
  \expanded{\expandafter\MyProdLoop\expandafter{\the\numexpr(#3)\relax}{#1}{1}{#2}{}}%
}%
\newcommand\MyProdLoop[5]{%
  % #1 - highest array index; #2 - array-macro; #3 - 1 or empty ; 
  % #4 - current array index;  #5 - result currently calculated so far; 
  \ifnum\numexpr(#4)\relax>\numexpr(#1)\relax
  \expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi
  {%
    \expanded{%
      \unexpanded{\MyProdLoop{#1}{#2}}{}{\the\numexpr(#4)+1\relax}{\bigintcalcMul{#3#5}{#2{#4}}}%
    }%
  }{\unexpanded{#5}}%
}
\makeatother

如果你足够大胆

  • 均需使用足够新的 LaTeX 发行版来配合 l3kernel 软件包 [2021-05-07] 或更高版本\clist_map_tokens:nn
  • 并相信 l3kernel 内部实现 \clist_map_tokens:nn不会很快改变,

然后,您可以实现一个可扩展的宏\ArrayElementProduct,其中恰好两个扩展步骤生成结果,该结果作为其参数,采用数组宏标记和以逗号分隔的数组索引列表,并通过迭代逗号列表,对每个逗号列表项应用一个宏,该宏将索引号由逗号列表项表示的数组元素与迄今为止收集的结果相乘,从而通过在每次迭代中挂接到内部映射中断\clist_map_tokens:nn来维护迄今为止收集的结果:\clist_map_tokens:nn

\documentclass[]{article}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{math}% for numbered Variables \x{1}, \x{2}, .... 
\usepackage{bigintcalc}% for big numbers  (e.g. 9^66)

\ExplSyntaxOn
\cs_new:Npn \ArrayElementProduct #1#2 {
  \exp:w
  \exp_last_unbraced:No
  \MyStuff_arrayelementproduct_hook_in_clist_mapbreak_initial:wn
  {
    \clist_map_tokens:nn {#2}{ \MyStuff_arrayelementproduct_hook_in_clist_mapbreak:nnwn{#1} }
  }
}
\cs_new:Npn \MyStuff_arrayelementproduct_hook_in_clist_mapbreak_initial:wn #1 \prg_break_point:Nn \clist_map_break: #2 {
  #1 \prg_break_point:Nn \clist_map_break: { \exp_end: }
}
\cs_new:Npn \MyStuff_arrayelementproduct_hook_in_clist_mapbreak:nnwn #1#2#3 \prg_break_point:Nn \clist_map_break: #4 {
  \exp_args:Nne \use:n { #3 \prg_break_point:Nn \clist_map_break:} {
    \tl_if_empty:oTF{\use_none:n #4} {
      \exp_not:n {\exp_end:} \bigintcalcMul{1}
    }{
      \exp_not:n {\exp_end:} \bigintcalcMul{\use_none:n #4}
    }{#1{#2}} 
  }
}
\ExplSyntaxOff

\begin{document}

\section*{Define Variables}
\tikzmath{%
  int \i;
  \i=0;
  for \xValue in {2, 3, 7, 42, 1806}{%
    \i=\numexpr\i+1\relax;
    \x{\i}=\xValue;  
  };%
}%
\(x(1) = \x{1}\), \hfill
\(x(2) = \x{2}\), \hfill
\(x(3) = \x{3}\), \hfill
\(x(4) = \x{4}\), \hfill
\(x(5) = \x{5}\)%

\section*{Multiply Variables}
\(x(1) \times x(3) \times x(5) = \x{1} \times \x{3} \times \x{5} = \ArrayElementProduct{\x}{1, 3 , 5}\)

\section*{Test edge cases of input}

\verb*|(\ArrayElementProduct{\x}{1, 3 ,,, , 5})|: (\ArrayElementProduct{\x}{1, 3 ,,, , 5})

\noindent
\verb*|(\ArrayElementProduct{\x}{4})|: (\ArrayElementProduct{\x}{4})

\noindent
\verb*|(\ArrayElementProduct{\x}{,  ,,, , })|: (\ArrayElementProduct{\x}{,  ,,, , })

\noindent
\verb*|(\ArrayElementProduct{\x}{,})|: (\ArrayElementProduct{\x}{,})

\noindent
\verb*|(\ArrayElementProduct{\x}{})|: (\ArrayElementProduct{\x}{})

\noindent
\verb*|(\ArrayElementProduct{\x}{ })|: (\ArrayElementProduct{\x}{ })

\end{document}

在此处输入图片描述

(我想知道我是否忽略了这种事情的官方界面。)

相关内容