计算 expl3 序列的部分和

计算 expl3 序列的部分和

如何计算整数序列的部分和?这是我目前得到的结果

\documentclass{article}
\usepackage{calc, forloop, xparse}

\ExplSyntaxOn
\seq_new:N \g_tmp_seq
\seq_new:N \g_partialsum_seq
\seq_set_from_clist:Nn \g_tmp_seq {3, 1, 2, 4, 0, 1}

\newcounter{i}
\newcounter{j}
\newcounter{lengthplusone}
\setcounter{lengthplusone}{\seq_count:N \g_tmp_seq + 1}

\forloop{i}{1}{ \value{i} < \value{lengthplusone} }{
  \seq_gput_right:Nn \g_partialsum_seq {0
    \forloop{j}{1}{ \value{j} < \value{i} }{
      + \seq_item:Nn \g_tmp_seq { \value{j} - 1}
    }
  }
}

\cs_new:Npn \partialsum #1 {
  \seq_item:Nn \g_partialsum_seq { #1 }
}
\ExplSyntaxOff

\begin{document}
\partialsum{1} % should be 0

\partialsum{2} % should be 3

\partialsum{3} % should be 4

\partialsum{4} % should be 6

\partialsum{5} % should be 10

\partialsum{6} % should be 10
\end{document}

不幸的是,总和并没有扩大,而且所有的值\partialsum都等于最后的总和。

答案1

我认为对 seq 使用 expl3 迭代更自然:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \g_tmp_seq
\seq_new:N \g_partialsum_seq
\seq_set_from_clist:Nn \g_tmp_seq {3, 1, 2, 4, 0, 1}
\seq_set_from_clist:Nn \g_partialsum_seq {0}
\tl_new:N\l_sum

\seq_map_inline:Nn\g_tmp_seq{
  \tl_set:Nx\l_sum{\int_eval:n{\l_sum+#1}}
  \seq_gput_right:NV \g_partialsum_seq \l_sum
}

\NewDocumentCommand\partialsum {m}{
  \seq_item:Nn \g_partialsum_seq { #1 }
}
\ExplSyntaxOff

\begin{document}
\partialsum{1} % should be 0

\partialsum{2} % should be 3

\partialsum{3} % should be 4

\partialsum{4} % should be 6

\partialsum{5} % should be 10

\partialsum{6} % should be 10
\end{document}

答案2

我完全放弃了calcforloop,因为你可以使用普通的 来完成所有操作expl3。作为奖励,你可以使命令可扩展,并使用可选参数来设置求和的起点。

与您的版本的主要区别在于代码不存储求和序列。每次使用该命令时,都会对选定的间隔进行求和。

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \g_noibe_numbers_seq
\seq_set_from_clist:Nn \g_noibe_numbers_seq {3, 1, 2, 4, 0, 1}
\NewExpandableDocumentCommand \partialsum { O{1} m }
  { \__noibe_partialsum:Nnnn \g_noibe_numbers_seq {#1-2} {#2-2} { } }
\cs_new:Npn \__noibe_partialsum:Nnnn #1 #2 #3 #4
  {
    \int_compare:nNnTF {#2} > {#3}
      { \int_eval:n {#4 0} }
      {
        \exp_args:Nf
        \__noibe_partialsum:nN { \int_eval:n {#2+1} } #1
          {#4} {#3}
      }
  }
\cs_new:Npn \__noibe_partialsum:nN #1 #2
  {
    \exp_args:Nf
    \__noibe_partialsum:nnNnn { \seq_item:Nn #2 {#1} + } {#1} #2
  }
\cs_new:Npn \__noibe_partialsum:nnNnn #1 #2 #3 #4 #5
  { \__noibe_partialsum:Nnnn #3 {#2} {#5} {#4#1} }
\ExplSyntaxOff
\begin{document}
\partialsum{1} % should be 0

\partialsum{2} % should be 3

\partialsum{3} % should be 4

\partialsum{4} % should be 6

\partialsum{5} % should be 10

\partialsum{6} % should be 10

\ifnum\partialsum{5}=\partialsum{6}
  The fifth item is zero.
\else
  The fifth item is nonzero.
\fi
\end{document}

答案3

使用更少的代码expl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\setsequence}{m}
 {% #1 = items
  \seq_set_from_clist:Nn \l_noibe_sequence_seq { #1 }
 }

\NewExpandableDocumentCommand{\partialsum}{m}
 {% #1 = (one more than the) number of items to sum
  \int_eval:n
   { 
    0 \int_step_function:nN { #1 - 1 } \__noibe_sequence_sum:n
   }
 }

\cs_new:Nn \__noibe_sequence_sum:n
 {
  \int_compare:nF { #1 > \seq_count:N \l_noibe_sequence_seq }
   {
    + \seq_item:Nn \l_noibe_sequence_seq { #1 }
   }
 }
\ExplSyntaxOff

\begin{document}

\setsequence{3, 1, 2, 4, 0, 1}

\partialsum{1} --- should be 0

\partialsum{2} --- should be 3

\partialsum{3} --- should be 4

\partialsum{4} --- should be 6

\partialsum{5} --- should be 10

\partialsum{6} --- should be 10

\partialsum{7} --- should be 11

\partialsum{8} --- should be 11

\end{document}

在此处输入图片描述

相关内容