使用 xfp 扩展除数集吗?

使用 xfp 扩展除数集吗?

我编写了一些代码来打印除数集但它不可扩展。

\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

相关内容