我试图将答案中的代码结合起来“使用 LaTeX 3 计算有限级数之和“ 和 ”使用 LaTeX 3 简化分数“自动计算有限和作为分数的分子或分母(在本例中为分子),然后自动减少该分数。
以下是我迄今为止尝试过的:
\documentclass{article}
\usepackage{siunitx}
\ExplSyntaxOn
% calculations
\cs_new_eq:NN \calc \fp_eval:n
% finite sum
\NewDocumentCommand{\computesum}{mmm}{
\compute_sum:nnn{#1}{#2}{#3}
}
\fp_new:N \l_partial_sum_fp
\cs_new_protected:Npn \compute_sum:nnn#1#2#3{
\fp_zero:N \l_partial_sum_fp
\int_step_inline:nnnn{#1}{1}{#2}{
\fp_add:Nn \l_partial_sum_fp{#3}
}
\num{\fp_use:N \l_partial_sum_fp}
}
% reduce fraction
\cs_new:Nn \gcd:nn{
\int_compare:nNnTF{#2} = {0}{#1}
{\gcd:ff{#2}{\int_mod:nn{#1}{#2}}}
}
\cs_generate_variant:Nn \gcd:nn{ff}
\int_new:N \l__tmp_int
\cs_new:Nn \reduced:nn{
\int_set:Nn \l__tmp_int{\gcd:nn{#1}{#2}}
\frac{\reduced_wrap:n{\int_eval:n{#1/\l__tmp_int}}}%
{\reduced_wrap:n{\int_eval:n{#2/\l__tmp_int}}}
}
\cs_set_eq:NN \reduced_wrap:n \relax
\NewDocumentCommand\ReducedFractionWrapper{m}
{\cs_set_eq:NN \reduced_wrap:n#1}
\NewDocumentCommand\ReducedFraction{o>{\SplitList{/}}m}{
\group_begin:
\IfValueT{#1}{\reducedFractionWrapper{#1}}
\int_compare:nTF
{\tl_count:n{#2} = 2}
{\reduced:nn#2}
{}
\group_end:
}
\ExplSyntaxOff
\begin{document}
\def\maksimum{20}
\def\produkt{25}
\ReducedFractionWrapper{\num}
\[
\ReducedFraction{\computesum{1}{\maksimum}{min(floor(\produkt/#1),\maksimum)+2}/\calc{(\maksimum+1)^2}}
% = \frac{117}{441}
% = \frac{13}{49}
\]
\end{document}
这将给出以下错误消息:
! Missing number, treated as zero.
<to be read again>
\tex_let:D
l.62 .../#1),\maksimum)+2}/\calc{(\maksimum+1)^2}}
我认为该错误是由于#1
但我不知道如何修复它。
我该如何更改代码才能让它实现我想要的效果?
答案1
您不能在那里进行分配\computesum
。一个基本的选择是\computesum
先进行分配,然后再\usesum
进行计算。
\NewDocumentCommand \computesum { m m m }
{ \svend_compute_sum:Nnnn \l_svend_partial_sum_fp { #1 } { #2 } { #3 } }
\NewDocumentCommand \usesum { }
{ \svend_use_sum:N \l_svend_partial_sum_fp }
\fp_new:N \l_svend_partial_sum_fp
\cs_new_protected:Nn \svend_compute_sum:Nnnn
{
\fp_zero:N #1
\int_step_inline:nnnn { #2 } { 1 } { #3 } { \fp_add:Nn #1 { #4 } }
}
\cs_new:Npn \svend_use_sum:N { \fp_use:N }
...
\[
\computesum{1}{\maksimum}{min(floor(\produkt/#1),\maksimum)+2}
\ReducedFraction
{\usesum/\calc{(\maksimum+1)^2}}
% = \frac{117}{441}
% = \frac{13}{49}
\]
顺便说一下,你有一些混合的东西,比如\num
里面 \svend_compute_sum:Nnnn
,为什么?我觉得你应该把代码写清楚一点。比如,你用\int_compare:nNnTF
while:nNnT
就够了。
另外,请遵循缩进规则expl3
,我认为这有助于提高可读性很多。
这是第一轮尝试格式化并使用更好的名称(注意,我既不是恩里科也不约瑟夫)。
\documentclass{scrartcl}
\usepackage{xparse,siunitx}
\ExplSyntaxOn
\cs_set_eq:NN \calc \fp_eval:n
\NewDocumentCommand \computesum { m m m }
{ \svend_compute_sum:Nnnn \l_svend_partial_sum_fp { #1 } { #2 } { #3 } }
\DeclareExpandableDocumentCommand \usesum { }
{ \svend_use_sum:N \l_svend_partial_sum_fp }
\fp_new:N \l_svend_partial_sum_fp
\cs_new_protected:Nn \svend_compute_sum:Nnnn
{
\fp_zero:N #1
\int_step_inline:nnnn { #2 } { 1 } { #3 } { \fp_add:Nn #1 { #4 } }
}
\cs_new:Npn \svend_use_sum:N { \fp_use:N }
\cs_new:Nn \svend_gcd:nn
{
\int_compare:nNnTF { #2 } = { 0 } { #1 }
{ \svend_gcd:ff { #2 } { \int_mod:nn { #1 } { #2 } } }
}
\cs_generate_variant:Nn \svend_gcd:nn { ff }
\int_new:N \l_svend_tmp_int
\cs_new:Nn \svend_reduced:nn
{
\int_set:Nn \l_svend_tmp_int { \svend_gcd:nn { #1 } { #2 } }
\frac{ \svend_reduced_wrap:n { \int_eval:n { #1/\l_svend_tmp_int } } }
{ \svend_reduced_wrap:n { \int_eval:n { #2/\l_svend_tmp_int } } }
}
\cs_set_eq:NN \svend_reduced_wrap:n \use:n
\NewDocumentCommand \ReducedFractionWrapper { m }
{ \cs_set_eq:NN \svend_reduced_wrap:n #1 }
\NewDocumentCommand \ReducedFraction { o >{\SplitList{/}} m }
{
\group_begin:
\IfValueT{#1}{\reducedFractionWrapper{#1}}
\int_compare:nNnT { \tl_count:n { #2 } } = { 2 }
{ \svend_reduced:nn #2 }
\group_end:
}
\ExplSyntaxOff
\begin{document}
\def\maksimum{20}
\def\produkt{25}
\ReducedFractionWrapper\num
\[
\computesum{1}{\maksimum}{min(floor(\produkt/#1),\maksimum)+2}
\ReducedFraction
{\usesum/\calc{(\maksimum+1)^2}}
% = \frac{117}{441}
% = \frac{13}{49}
\]
\end{document}