我怎样才能制定一个多项式相乘的方案?

我怎样才能制定一个多项式相乘的方案?

我想创建一个系数方案来乘以多项式,例如P(x) = x^2 + 2x + 3如下Q(x) = 4x^2 + 5x + 6图所示:

在此处输入图片描述

我亲手尝试过

\documentclass[12pt,a4paper]{article}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{ polynomial}
\usepackage{polynom}
\usepackage{fourier}
\begin{document}
$P(x) = \polynomial{1,2,3}$ 

$Q(x) = \polynomial{4,5,6}$

\[\begin{matrix}
   {} & {} & 1 & 2 & 3  \\
   {} & {} & 4 & 5 & 6  \\
   {} & {} & 6 & 12 & 18  \\
   {} & 5 & 10 & 15 & {}  \\
   4 & 8 & 12 & {} & {}  \\
   4 & 13 & 28 & 32 & 18 
\end{matrix}\] 
\end{document}

如何自动创建方案(例如,通过使用polynom包与多项式除法的应用一样)?

答案1

这是一个expl3版本

\documentclass{article}
\usepackage{xparse,booktabs}

\ExplSyntaxOn
\NewDocumentCommand{\polymult}{mm}
 {
  \minthao_polymult_compute:nn { #1 } { #2 }
  \minthao_polymult_display:
 }

\seq_new:N \l_minthao_polymult_first_seq   % coefficients of first factor
\seq_new:N \l_minthao_polymult_second_seq  % coefficients of second factor
\seq_new:N \l_minthao_polymult_result_seq  % coefficients of result
\seq_new:N \l_minthao_polymult_temp_seq    % temporary usage
\int_new:N \l_minthao_polymult_first_int   % degree of first factor + 1
\int_new:N \l_minthao_polymult_second_int  % degree of second factor + 1
\int_new:N \l_minthao_polymult_temp_int    % temporary usage
\tl_new:N \l_minthao_polymult_tempa_tl     % current coefficient (first factor)
\tl_new:N \l_minthao_polymult_tempb_tl     % current coefficient (second factor)
\tl_new:N \l_minthao_polymult_body_tl      % table body

\cs_new_protected:Npn \minthao_polymult_compute:nn #1 #2
 {
  \seq_set_split:Nnn \l_minthao_polymult_first_seq { , } { #1 }
  \seq_set_split:Nnn \l_minthao_polymult_second_seq { , } { #2 }
  \seq_clear:N \l_minthao_polymult_result_seq
  \int_set:Nn \l_minthao_polymult_first_int
   {
    \seq_count:N \l_minthao_polymult_first_seq
   }
  \int_set:Nn \l_minthao_polymult_second_int
   {
    \seq_count:N \l_minthao_polymult_second_seq
   }
  \int_step_inline:nnnn
   { 2 } % start
   { 1 } % step
   { \l_minthao_polymult_first_int + \l_minthao_polymult_second_int } % end
   {
    \int_zero:N \l_minthao_polymult_temp_int
    % compute the coefficient of degree ##1 - 2
    \int_step_inline:nnnn { 0 } { 1 } { ##1 - 2 }
     {
      % get the coefficients, we'll use 0 if above the degree
      \tl_set:Nx \l_minthao_polymult_tempa_tl
       { \seq_item:Nn \l_minthao_polymult_first_seq { ####1 + 1 } }
      \tl_set:Nx \l_minthao_polymult_tempb_tl
       { \seq_item:Nn \l_minthao_polymult_second_seq { ##1 - ####1 - 1 } }
      % compute the coefficient of the product at the current degree
      \int_add:Nn \l_minthao_polymult_temp_int
       {
        \tl_if_empty:NTF \l_minthao_polymult_tempa_tl { 0 } { \l_minthao_polymult_tempa_tl }
        *
        \tl_if_empty:NTF \l_minthao_polymult_tempb_tl { 0 } { \l_minthao_polymult_tempb_tl }
       }
     }
    % append the coefficient
    \seq_put_right:Nx \l_minthao_polymult_result_seq
     {
      \int_to_arabic:n { \l_minthao_polymult_temp_int }
     }
   }
 }

\cs_new_protected:Npn \minthao_polymult_display:
 {
  \tl_clear:N \l_minthao_polymult_body_tl
  \__minthao_polymult_build_row:Nnn \l_minthao_polymult_first_seq { 1 } { 0 }
  \__minthao_polymult_build_row:Nnn \l_minthao_polymult_second_seq { 1 } { 0 }
  \tl_put_right:Nn \l_minthao_polymult_body_tl { \midrule }
  \int_step_inline:nnnn { 1 } { 1 } { \l_minthao_polymult_second_int }
   {
    \__minthao_polymult_build_row:Nnn \l_minthao_polymult_first_seq
     { \seq_item:Nn \l_minthao_polymult_second_seq { ##1 } } { ##1 - 1 }
   }
  \tl_put_right:Nn \l_minthao_polymult_body_tl { \midrule }
  \__minthao_polymult_build_row:Nnn \l_minthao_polymult_result_seq { 1 } { 0 }
  \begin{array}{*{\seq_count:N \l_minthao_polymult_result_seq}{c}}
  \tl_use:N \l_minthao_polymult_body_tl
  \end{array}
 }

\cs_new_protected:Npn \__minthao_polymult_build_row:Nnn #1 #2 #3
 {% #1 = sequence to use, #2 = multiplier, #3 = right padding
  \seq_clear:N \l_minthao_polymult_temp_seq
  \seq_map_inline:Nn #1
   {
    \seq_put_right:Nx \l_minthao_polymult_temp_seq
     { \int_to_arabic:n { ##1 * #2 } }
   }
  \seq_reverse:N \l_minthao_polymult_temp_seq
  % add the left padding
  \prg_replicate:nn
   {% number of repetitions:
    -1*(#3) + 
    \seq_count:N \l_minthao_polymult_result_seq -
    \seq_count:N \l_minthao_polymult_temp_seq
   }
   {% add blank entries
    \seq_put_left:Nn \l_minthao_polymult_temp_seq { }
   }
  \tl_put_right:Nx \l_minthao_polymult_body_tl
   { \seq_use:Nn \l_minthao_polymult_temp_seq { & } }
  \tl_put_right:Nn \l_minthao_polymult_body_tl { \\ }
 }

\ExplSyntaxOff

\begin{document}
\[
\polymult{3,2,1}{6,5,4}
\qquad
\polymult{1,1,1,1,1}{-1,1}
\]
\[
\polymult{-2,4,1,-3,10,-10}{-1,8,7,5,2,4}
\]
\end{document}

在此处输入图片描述

答案2

您可以尝试宏\mulscheme。我写它是为了回答您的问题。用法是:

\mulscheme {1 2 3} {4 5 6}
\mulscheme {3 4} {2 3 4 5}  etc..

第一个例子的结果和您所展示的相同。

实现如下:

\newcount\totA \newcount\totB  \newcount\tmpnum \newcount\spacenum
\def\mulscheme#1#2{%
   \tmpnum=0\def\tmp{A}\mulA #1 {} \totA=\tmpnum % reading first parameter
   \tmpnum=0\def\tmp{B}\mulA #2 {} \totB=\tmpnum % reading second parameter
   \advance\tmpnum by\totA \edef\totT{\the\tmpnum}% sum of totA and totB
   \def\linemul{} \tmpnum=0
   \loop \ifnum\tmpnum<\totB \advance\tmpnum by1 \mulC \repeat
   \edef\linemul{\linemul \mulB#1 {} }%
   \edef\muldata{\expandafter\mulF\linemul!\cr}% first line with first parameter
   \def\linemul{} \tmpnum=0
   \loop \ifnum\tmpnum<\totA \advance\tmpnum by1 \mulC \repeat
   \edef\linemul{\linemul \mulB#2 {} }% second line with second parameter
   \edef\muldata{\muldata\expandafter\mulF\linemul!\cr\noalign{\mulG\hrule\smallskip}}%
   \spacenum=0
   \loop \def\linemul{}%
         {\tmpnum=0 \loop \ifnum\tmpnum<\spacenum \advance\tmpnum by1 \mulC \repeat}%
         {\loop \mulD \advance\totA by-1 \ifnum\totA>0 \repeat}%
         {\tmpnum=\totB \loop \ifnum\tmpnum>1 \advance\tmpnum by-1 \mulC \repeat}%
         \edef\muldata{\muldata\linemul\cr}%
         \advance\spacenum by1 \advance\totB by-1
         \ifnum\totB>0 \repeat
   \tmpnum=\totT \advance\tmpnum by-1 \def\linemul{}%
   \loop \edef\linemul{\linemul\mulE \csname mulT:\the\tmpnum\endcsname}%
         \global\expandafter\let\csname mulT:\the\tmpnum\endcsname=\relax
         \advance\tmpnum by-1 \ifnum\tmpnum>0 \repeat
   \vbox{\halign{&\ \hfil$##$\ \cr\muldata\noalign{\smallskip\hrule\smallskip}\linemul\cr}}%
}
\def\mulA #1 {\ifx^#1^\else
   \advance\tmpnum by1
   \expandafter\def\csname mul\tmp:\the\tmpnum\endcsname{#1}%
   \expandafter\mulA\fi}
\def\mulB #1 {\ifx^#1^\else #1&\expandafter\mulB\fi}
\def\mulC{\xdef\linemul{\space\mulE\linemul}}
\def\mulD{\tmpnum=\csname mulA:\the\totA\endcsname 
   \multiply\tmpnum by\csname mulB:\the\totB\endcsname
   \xdef\linemul{\the\tmpnum \mulE\linemul}
   \advance\spacenum by1
   \advance\tmpnum by0\csname mulT:\the\spacenum\endcsname
   \expandafter\xdef\csname mulT:\the\spacenum\endcsname{\the\tmpnum}%
}
\def\mulE{\ifx\linemul\empty \else&\fi}
\def\mulF#1&!{#1}
\def\mulG{\nointerlineskip\vbox to0pt{\kern-1.1\baselineskip\hbox{$\times$}\vss}\smallskip}

\mulscheme {1 2 3} {4 5 6}
\bigskip\mulscheme {3 4} {2 3 4 5}

\newcount使用 TeX 基元和宏。我尝试在纯 TeX 中使用,但我希望它也可以在 LaTeX 中使用。此宏的主要原理是计算 中的行\linemul并将其存储到 中\muldata。完成所有计算后,\halign{...\muldata}将使用 。

答案3

灵感来自Mathematica Stackexchange 上最近的一个问题,我重新审视了这一点,利用l3fp可以操作数字元组并将它们乘以标量的事实简化了 egreg 的代码。我还添加了一些键值设置,以明确写入变量的幂(可以选择其名称),避免写入x^0,并隐藏具有零系数的项。

编辑:请注意,在我的代码中,系数是从最高程度到最低程度给出的,而在 egreg 的代码中则相反。

编辑:我增加了添加颜色等的可能性。

\documentclass{article}
\usepackage{xparse,array,booktabs,multirow,xcolor,colortbl}

\ExplSyntaxOn
\NewDocumentCommand{\polymult}{O{}mm}
  {
    \group_begin: % to localize the setting of the variable
      \keys_set:nn { polymult } {#1}
      \polymult_compute:nn {#2} {#3}
      \polymult_display:
    \group_end:
  }

\fp_new:N \l_polymult_P_fp        % tuple of coefs of first factor
\fp_new:N \l_polymult_Q_fp        % tuple of coefs of second factor
\fp_new:N \l_polymult_PQ_fp       % tuple of coefs of result
\int_new:N \l_polymult_degP_int   % degree of first factor
\int_new:N \l_polymult_degQ_int   % degree of second factor
\int_new:N \l_polymult_ndeg_int   % tracks (degQ - current degree)
\int_new:N \l_polymult_row_int    % track which row we are on (differs from ndeg if zeros are hidden)
\int_new:N \l_polymult_nrows_int  % number of rows of calculation displayed
\int_new:N \l_polymult_term_int   % tracks which term we are on
\seq_new:N \l_polymult_rows_seq   % coefs of each intermediate row
\tl_new:N \l_polymult_tmp_tl      % temporary usage
\tl_new:N \l_polymult_var_tl      % variable to use (empty for a bare table)
\bool_new:N \l_polymult_first_term_bool
\bool_new:N \l_polymult_hide_zeros_bool
\bool_new:N \l_polymult_simplify_bool
\bool_new:N \l_polymult_align_signs_bool
\tl_new:N \l_polymult_start_preamble_tl
\tl_new:N \l_polymult_stop_preamble_tl
\tl_new:N \l_polymult_start_P_row_tl
\tl_new:N \l_polymult_stop_P_row_tl
\tl_new:N \l_polymult_start_Q_row_tl
\tl_new:N \l_polymult_stop_Q_row_tl
\tl_new:N \l_polymult_start_first_row_tl
\tl_new:N \l_polymult_stop_first_row_tl
\tl_new:N \l_polymult_start_typical_row_tl
\tl_new:N \l_polymult_stop_typical_row_tl
\tl_new:N \l_polymult_start_last_row_tl
\tl_new:N \l_polymult_stop_last_row_tl
\tl_new:N \l_polymult_start_PQ_row_tl
\tl_new:N \l_polymult_stop_PQ_row_tl

\keys_define:nn { polymult }
  {
    var .tl_set:N = \l_polymult_var_tl ,
    var .initial:n = { } ,
    hide-zeros .bool_set:N = \l_polymult_hide_zeros_bool ,
    simplify .bool_set:N = \l_polymult_simplify_bool ,
    align-signs .bool_set:N = \l_polymult_align_signs_bool ,
    start-preamble .tl_set:N = \l_polymult_start_preamble_tl ,
    stop-preamble .tl_set:N = \l_polymult_stop_preamble_tl ,
    start-P-row .tl_set:N = \l_polymult_start_P_row_tl ,
    stop-P-row .tl_set:N = \l_polymult_stop_P_row_tl ,
    start-Q-row .tl_set:N = \l_polymult_start_Q_row_tl ,
    stop-Q-row .tl_set:N = \l_polymult_stop_Q_row_tl ,
    start-first-row .tl_set:N = \l_polymult_start_first_row_tl ,
    stop-first-row .tl_set:N = \l_polymult_stop_first_row_tl ,
    start-typical-row .tl_set:N = \l_polymult_start_typical_row_tl ,
    stop-typical-row .tl_set:N = \l_polymult_stop_typical_row_tl ,
    start-last-row .tl_set:N = \l_polymult_start_last_row_tl ,
    stop-last-row .tl_set:N = \l_polymult_stop_last_row_tl ,
    start-PQ-row .tl_set:N = \l_polymult_start_PQ_row_tl ,
    stop-PQ-row .tl_set:N = \l_polymult_stop_PQ_row_tl ,
    operations-times .tl_set:N = \l_polymult_times_tl ,
    operations-times .initial:n = {\times} ,
    operations-plus .tl_set:N = \l_polymult_plus_tl ,
    operations-plus .initial:n = {+} ,
    operations .meta:n = {
      start-preamble = {@{}c@{\,}} ,
      start-P-row = {&} ,
      start-Q-row = {\l_polymult_times_tl&} ,
      start-first-row = {&} ,
      start-typical-row = {\l_polymult_plus_tl&} ,
      start-last-row = {\l_polymult_plus_tl&} ,
      start-PQ-row = {&} ,
    },
    halfway-operations .meta:n = {
      start-preamble = {@{}c@{}} ,
      start-P-row = {\multirow{2}{1em}{$\l_polymult_times_tl$}&} ,
      start-Q-row = {&} ,
      start-first-row = {\multirow{\l_polymult_nrows_int}{1em}{$\l_polymult_plus_tl$}&} ,
      start-typical-row = {&} ,
      start-last-row = {&} ,
      start-PQ-row = {&} ,
    }
  }


\cs_generate_variant:Nn \clist_map_inline:nn { xn }
\cs_generate_variant:Nn \clist_count:n { e }

\cs_new:Npn \__polymult_tuple_to_clist:n #1
  { \exp_args:Nf \__polymult_tuple_to_clist_aux:n { \fp_to_tl:n {#1} } }
\cs_new:Npn \__polymult_tuple_to_clist_aux:n #1
  {
    \tl_if_head_eq_charcode:nNTF {#1} ( % )
      { \__polymult_tuple_to_clist_aux:w #1 } {#1}
  }
\cs_new:Npn \__polymult_tuple_to_clist_aux:w (#1) {#1}

\cs_new_protected:Npn \polymult_compute:nn #1 #2
  {
    % Parse the input, evaluate the coefficients only once
    \fp_set:Nn \l_polymult_P_fp {#1}
    \fp_set:Nn \l_polymult_Q_fp {#2}
    \int_set:Nn \l_polymult_degP_int
      { \clist_count:e { \fp_to_tl:N \l_polymult_P_fp } - 1 }
    \int_set:Nn \l_polymult_degQ_int
      { \clist_count:e { \fp_to_tl:N \l_polymult_Q_fp } - 1 }
    %
    % Variables to track the rows, and the total sum (initially zero)
    \int_zero:N \l_polymult_row_int
    \int_zero:N \l_polymult_ndeg_int
    \seq_clear:N \l_polymult_rows_seq
    \fp_set:Nn \l_polymult_PQ_fp
      { 0 \prg_replicate:nn { \l_polymult_degP_int + \l_polymult_degQ_int } { ,0 } }
    %
    % Loop through terms of Q, starting from the highest degree,
    % so the rows here are added from right (bottom) to left (top)
    \clist_map_inline:xn
      { \__polymult_tuple_to_clist:n { \l_polymult_Q_fp } }
      {
        \bool_if:nF { \l_polymult_hide_zeros_bool && \fp_compare_p:n { ##1 = 0 } }
          { \int_incr:N \l_polymult_row_int }
        \tl_set:Nx \l_polymult_tmp_tl
          { \__polymult_tuple_to_clist:n { ##1 * \l_polymult_P_fp } }
        \seq_put_left:Nx \l_polymult_rows_seq { \l_polymult_tmp_tl }
        \fp_add:Nn \l_polymult_PQ_fp
          {
            \prg_replicate:nn { \l_polymult_ndeg_int } { 0, }
            \l_polymult_tmp_tl
            \prg_replicate:nn { \l_polymult_degQ_int - \l_polymult_ndeg_int } { ,0 }
          }
        \int_incr:N \l_polymult_ndeg_int
      }
    \int_set_eq:NN \l_polymult_nrows_int \l_polymult_row_int
  }

\cs_new_protected:Npn \polymult_display:
  {
    % Display P and Q, with a suitable number of empty slots before
    \tl_clear:N \l_polymult_body_tl
    \__polymult_build_row:nfnn { P }
      { \__polymult_tuple_to_clist:n { \l_polymult_P_fp } }
      { \l_polymult_degQ_int } { 0 }
    \__polymult_build_row:nfnn { Q }
      { \__polymult_tuple_to_clist:n { \l_polymult_Q_fp } }
      { \l_polymult_degP_int } { 0 }
    %
    \tl_put_right:Nn \l_polymult_body_tl { \midrule }
    \int_zero:N \l_polymult_row_int
    \int_zero:N \l_polymult_ndeg_int
    \seq_map_inline:Nn \l_polymult_rows_seq
      {
        % detecting zero rows
        \bool_if:nF
          { \l_polymult_hide_zeros_bool && \fp_compare_p:n { (##1) = 0*(##1) } }
          {
            \int_incr:N \l_polymult_row_int
            \__polymult_build_row:fnnn
              {
                \int_case:nnF \l_polymult_row_int
                  {
                    { 1 } { first }
                    { \l_polymult_nrows_int } { last }
                  }
                  { typical }
              }
              {##1}
              { \l_polymult_degQ_int - \l_polymult_ndeg_int }
              { \l_polymult_ndeg_int }
          }
        \int_incr:N \l_polymult_ndeg_int
      }
    \tl_put_right:Nn \l_polymult_body_tl { \midrule }
    \tl_set:Nx \l_polymult_tmp_tl
      { \__polymult_tuple_to_clist:n { \l_polymult_PQ_fp } }
    \__polymult_build_row:nfnn { PQ } \l_polymult_tmp_tl { 0 } { 0 }
    \exp_args:Nnx \begin{array}
      {
        \l_polymult_start_preamble_tl
        \bool_if:NTF \l_polymult_align_signs_bool
          {
            * { \int_eval:n { 2 * \clist_count:N \l_polymult_tmp_tl } }
            { @{} r @{} }
          }
          { * { \clist_count:N \l_polymult_tmp_tl } { r } }
        \l_polymult_stop_preamble_tl
      }
      \tl_use:N \l_polymult_body_tl
    \end{array}
  }

\cs_generate_variant:Nn \__polymult_build_row:nnnn { f , nf }
\cs_new_protected:Npn \__polymult_build_row:nnnn #1#2#3#4
  {
    % #1 = row name , #2 = clist to use, #3 = left padding, #4 = right padding
    \tl_put_right:Nx \l_polymult_body_tl
      {
        \exp_not:v { l_polymult_start_#1_row_tl }
        \prg_replicate:nn { \bool_if:NT \l_polymult_align_signs_bool { 2 * } (#3) } { & }
      }
    \bool_set_true:N \l_polymult_first_term_bool
    \int_set:Nn \l_polymult_term_int
      { \l_polymult_degP_int + \l_polymult_degQ_int - (#3) }
    \clist_map_inline:nn {#2}
      {
        \tl_put_right:Nx \l_polymult_body_tl
          {
            \bool_if:NF \l_polymult_first_term_bool { & }
            \bool_if:nTF % BLF here
              { \l_polymult_hide_zeros_bool && \fp_compare_p:n { ##1 = 0 } }
              { & }
              { \__polymult_monomial:nN {##1} \l_polymult_term_int }
          }
        \bool_set_false:N \l_polymult_first_term_bool
        \int_decr:N \l_polymult_term_int
      }
    \tl_put_right:Nx \l_polymult_body_tl
      {
        \prg_replicate:nn { \bool_if:NT \l_polymult_align_signs_bool { 2 * } (#4) } { & }
        \exp_not:v { l_polymult_stop_#1_row_tl }
        \exp_not:N \\
      }
  }
\cs_new:Npn \__polymult_monomial:nN #1#2
  {
    \fp_compare:nTF { #1 < 0 }
      { \bool_if:NTF \l_polymult_align_signs_bool { {} - {} } { - } }
      {
        \bool_if:NF \l_polymult_first_term_bool
          { \tl_if_empty:NF \l_polymult_var_tl { {} + {} } }
      }
    \bool_if:NT \l_polymult_align_signs_bool { & }
    \bool_if:NTF \l_polymult_simplify_bool
      {
        \int_compare:nNnTF {#2} = 0
          { \fp_abs:n {#1} }
          {
            \tl_if_empty:NTF \l_polymult_var_tl
              { \fp_abs:n {#1} }
              {
                \fp_compare:nTF { \fp_abs:n {#1} = 1 } { } { \fp_abs:n {#1} }
                \exp_not:N \l_polymult_var_tl
                \int_compare:nNnF {#2} = 1 { ^ { \int_use:N #2 } }
              }
          }
      }
      {
        \fp_abs:n {#1}
        \tl_if_empty:NF \l_polymult_var_tl
          { \exp_not:N \l_polymult_var_tl ^ { \int_use:N #2 } }
      }
  }

\ExplSyntaxOff

\NewDocumentCommand{\minhthienpolymult} {O{}} {%
  \polymult[align-signs,
    var=x,
    simplify,
    hide-zeros,
    halfway-operations,
    operations-times = \color{orange}\times,
    operations-plus = \color{orange}+,
    start-last-row = \arrayrulecolor{blue}&,
    #1]}

\begin{document}
\[
\polymult[halfway-operations, align-signs, var=\mathcal{B}, simplify, hide-zeros]{-1,2,3}{4,5,1,0,6}
\qquad
\polymult[align-signs, var=x, hide-zeros]{1,1,1,1,1}{1,-1}
\]
\[
\polymult{-10,10,-3,1,4,-2}{4,2,5,7,8,-1}
\]
\[
\polymult[operations, align-signs, var=x, simplify, hide-zeros]{-1,0,2}{-4,5,0,6}
\quad
\polymult[align-signs, var=a ,simplify]{1,0,-2,0,-1}{1,-1}
\]
\[
\minhthienpolymult[var=x, hide-zeros=false]{1,1,-1}{2,-7,9}
\]
\end{document}

相关内容