将表中多行上的多项式对齐

将表中多行上的多项式对齐

我想格式化一个表格,每列都有多项式。这些多项式不一定具有相同的程度,其系数可以是任意有理数。多项式的项应以适当的方式显示,以使不同行上的项不会混淆(例如,x 3被误认为是 x 2)。

起初我使用tabular,但必须将每个多项式都包装在中$变得不方便,因此我按照建议使用了array+$这里

\documentclass{standalone}
\begin{document}
  $\begin{array}{r|r|r|r}
     d & u & v & q \\
     x^5 + 3x^3 + x^2 + 2x + 1 & 1 &  0 & \\
     x^4 + 5x^3 -5x^2 - 5x - 6 & 0 &  1 & \\
    5x^4 + 8x^3 +6x^2 + 8x + 1 & 1 & -x & x \\
  \end{array}$
\end{document}

得出以下结果。

前两个多项式的左侧部分未对齐。如何实现以下效果(其中项和运算符水平对齐)?

            d | u | v | q
--------------------------+-----+-----+---
x 5     + 3x 3 + x 2 + 2x + 1 | 1 | 0 |
   x 4 + 5x 3 - 5x 2 - 5x - 6 | 0 | 1 |
  5x 4 + 8x 3 + 6x 2 + 8x + 1 | 1 | -x | X

(该表显示了 ℚ[x] 中两个多项式的扩展欧几里得算法)

答案1

当多项式排列良好时,唯一宽度变化的部分是系数。因此,我为运算符 (+/-)、系数和 x n使用了单独的列。为了避免水平间距过大,我@{}在每个右对齐列说明符r(记录在array包中)。

使用该方法,多项式 f(x) 可以写成x^5 & & & + & 3x^3 & + & x^2 & + & 2x & + & 1。这在源代码中很难阅读(由于重复的&s 和x^is ),所以我定义了一些(递归)宏:

  1. \polyCols{N}创建 N 次重复r@{}r@{}...作为array选项。
  2. \poly[N]{..}{..}...创建一个次数为 的多项式N。例如\poly[2]{-}{5}{}{}{+}{1}展开为- & 5x^2 & & & + & 1 &

结果如下:

预览

\documentclass{standalone}
% #1 = deg(f), #2 = ignored, #3 = operator, #4 = coefficient
\newcommand\polyRecursiveImplementation[4][0]{
  #3 &
  \ifx\\#4\\ % Do not print a term if the coefficient is missing
  \else
    \ifnum#1=0  % Just show the coefficient for x^0
      #4
    \else
      \ifnum#1=1 % Show "x" if the exponent is 1.
        \if1#4\else#4\fi x
      \else      % Show "x^e" otherwise.
        \if1#4\else#4\fi x^{#1}
      \fi % \if1#4\else#4\fi = Only show the coefficient if it's not 1.
    \fi
  \fi
  &
  \ifnum0<#1
    \polyRecursiveImplementation[\the\numexpr#1-1]
  \fi
}

% Usage: \poly[deg(f)]{sign}{term} (repeat {..}{..} deg(f) times)
\newcommand\poly[3][0]{\polyRecursiveImplementation[#1]{}{#2}{#3}}

% Create a specifier for #1 polynomial terms.
\newcommand\polyCols[1]{
  \ifnum0<#1
    r@{}r@{}
    \polyCols{\the\numexpr#1-1}
  \fi
}

\begin{document}
$\begin{array}{
  \polyCols{6}@{\hskip\tabcolsep}|
  \polyCols{6}@{\hskip\tabcolsep}|
  \polyCols{6}@{\hskip\tabcolsep}|
  \polyCols{6}r
}
\multicolumn{12}{c|}{d} &
\multicolumn{12}{c|}{u} &
\multicolumn{12}{c|}{v} &
\multicolumn{12}{c}{q} & \\
\hline

\poly[5]{}{1}{}{}{+}{3}{+}{1}{+}{2}{+}{1}
\poly[5]{}{}{}{}{}{}{}{}{}{}{}{1}
\poly[5]{}{}{}{}{}{}{}{}{}{}{}{0}
\poly[5]{}{}{}{}{}{}{}{}{}{}{}{} \\

\poly[5]{}{}{}{1}{-}{5}{-}{5}{-}{5}{-}{6}
\poly[5]{}{}{}{}{}{}{}{}{}{}{}{0}
\poly[5]{}{}{}{}{}{}{}{}{}{}{}{1}
\poly[5]{}{}{}{}{}{}{}{}{}{}{}{} \\

\poly[5]{}{}{}{5}{+}{8}{+}{6}{+}{8}{+}{1}
\poly[5]{}{}{}{}{}{}{}{}{}{}{}{0}
\poly[5]{}{}{}{}{}{}{}{}{-}{1}{}{}
\poly[5]{}{}{}{}{}{}{}{}{}{1}{}{} \\

\end{array}$
\end{document}

代码详述

这是我的第一个非平凡宏,在构建它时我遇到了一些问题。以下是我发现的一些问题以及我如何解决它们:

  • 宏最多可以采用 9 个参数。这个答案展示了如何处理更多参数;通过以另一个宏的不完整调用结束一个宏。然后,另一个宏将处理剩余的参数,这样参数总数就可以超过 9 个。

  • 我的参数宏是递归的,但它必须在某个点结束。所以我从条件宏开始。

    % Example: Wrap n elements in parentheses
    \newcommand\foo[2]{ (#2) \ifnum0<#1 \foo{\the\numexpr#1-1} \fi}
    \foo{10}{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}
    

    这无法编译(! File ended while scanning use of \foo.)。显然,附加了\if...\if一个额外的变量。为了解决这个问题,我将第一个位置参数声明为可选(\newcommand[N][...]{...})并忽略第二个参数。
    使用这种构造,我可以将计数器作为参数传递给宏,并处理新元素。

    % #1 = count, #2 = ignored #3 = value to be wrapped in parentheses
    \newcommand\fooImpl[3][0]{ (#3) \ifnum0<#1 \fooImpl[\the\numexpr#1-1] \fi}
    \newcommand\foo[2]{\fooImpl[#1]{}{#2}}
    \foo{10}{0)(1}{2}{3}{4}{5}{6}{7}{8}{9}{10}
    % Output : (0)(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)
    

    上述最小示例每次迭代消耗一个参数,而我的实际宏(\poly\polyRecursiveImplementation)则需要两个。
    为了增强可读性,我将的第一个参数标记\poly为可选,以便清楚地看到[和之间的值]用于指定多项式项的数量,而{...}{...}指定每个项的符号和系数。

  • 最初我想省略最后一句&省略宏中最后一个项的最后一个。由于以下原因,这种条件逻辑无法实现:“不完整的 \ifnum;行后的所有文本均被忽略”),因此每一行都有一个多余的&

注意,参数数量必须匹配。如果你在复制并更改我的示例后出现错误,请检查参数数量是否匹配(\foo[N]{1}{2}...{N+1})。

相关内容