我编写了一些代码来打印除数集但它不可扩展。
\input expl3-generic.tex
\def\divisors#1{%
\def\L{1}%
\def\M{#1}%
\def\x{2}%
\loop
\ifnum \fpeval{floor(#1/\x) = #1/\x} = 1\relax
\edef\L{\L, \x}
\ifnum \fpeval{\x = #1/\x} = 0 \edef\M{\fpeval{floor(#1/\x)}, \M} \fi
\fi
\edef\x{\fpeval{\x + 1}}%
\ifnum \fpeval{\x > sqrt #1} = 0%
\repeat
\L, \M}
\ExplSyntaxOn
\cs_new:Npn \fpeval #1
{ \fp_eval:n { #1 } }
\ExplSyntaxOff
$\divisors{625}$% Prints: 1, 5, 25, 125, 625
\bye
您能想象一个可扩展的解决方案吗?我知道我可以使用 LuaTeX 来实现这一点,但用 TeX 编程确实很有趣。;)
答案1
使用简单的暴力方法
\input expl3-generic.tex
\ExplSyntaxOn
\cs_new:Npn \divisors #1
{
1,~
\__divisors_aux:nn { 2 } {#1}
}
\cs_new:Npn \__divisors_aux:nn #1#2
{
\int_compare:nNnTF {#1} = {#2}
{#2}
{
\fp_compare:nNnT { #2 / #1 } = { floor ( #2 / #1 ) } { #1 , ~ }
\exp_args:Ne \__divisors_aux:nn { \int_eval:n { #1 + 1 } } {#2}
}
}
\ExplSyntaxOff
$\divisors{625}$
\bye
请注意,由于我们需要通过扩展来传递目标值,因此我们不能使用\int_step_function:nnN
(可扩展),而是我自己编写了一个简单的循环。
采用同样的想法,我们可以通过传递高值作为附加参数来使用更高效的循环
\input expl3-generic.tex
\ExplSyntaxOn
\cs_new:Npn \divisors #1
{
1,~
\__divisors_aux:nnn { 2 } {#1} {#1}
}
\cs_new:Npn \__divisors_aux:nnn #1#2#3
{
\fp_compare:nNnTF {#1} > { sqrt (#2) }
{#3}
{
\fp_compare:nNnTF { #2 / #1 } = { floor ( #2 / #1 ) }
{
#1 , ~
\fp_compare:nNnTF { #1 = #2 / #1 } = 0
{
\exp_args:Neee \__divisors_aux:nnn
{ \int_eval:n { #1 + 1 } } {#2}
{
\fp_to_int:n { floor ( #2 / #1 ) }
, ~ #3
}
}
{
\exp_args:Ne \__divisors_aux:nnn
{ \int_eval:n { #1 + 1 } } {#2} {#3}
}
}
{
\exp_args:Ne \__divisors_aux:nnn
{ \int_eval:n { #1 + 1 } } {#2} {#3}
}
}
}
\ExplSyntaxOff
$\divisors{625}$
\bye