tikz 中的帕斯卡三角形

tikz 中的帕斯卡三角形

我想排版帕斯卡三角形的顶部。为了得到带有二项式系数名称的三角形,即,{n \choose k}我使用了以下代码

\begin{tikzpicture}
\foreach \n in {0,...,4} {
  \foreach \k in {0,...,\n} {
    \node at (\k-\n/2,-\n) {${\n \choose \k}$};
  }
}
\end{tikzpicture}

结果是这样的 在此处输入图片描述

现在我想偷懒,对二项式系数的值做类似的事情,即{\n \choose \k}在节点标签中替换为\CalculateBinomialCoefficient{\n}{\k}计算\CalculateBinomialCoefficient二项式系数的假设宏。有人做过类似的事情吗?

结果应如下所示:在此处输入图片描述

答案1

这是一个使用 TeX 整数算法的解决方案。我重用了 PGF 定义的计数器,以避免必须声明新的计数器。

\documentclass{article}
\usepackage{tikz}

\makeatletter
\newcommand\binomialCoefficient[2]{%
    % Store values 
    \c@pgf@counta=#1% n
    \c@pgf@countb=#2% k
    %
    % Take advantage of symmetry if k > n - k
    \c@pgf@countc=\c@pgf@counta%
    \advance\c@pgf@countc by-\c@pgf@countb%
    \ifnum\c@pgf@countb>\c@pgf@countc%
        \c@pgf@countb=\c@pgf@countc%
    \fi%
    %
    % Recursively compute the coefficients
    \c@pgf@countc=1% will hold the result
    \c@pgf@countd=0% counter
    \pgfmathloop% c -> c*(n-i)/(i+1) for i=0,...,k-1
        \ifnum\c@pgf@countd<\c@pgf@countb%
        \multiply\c@pgf@countc by\c@pgf@counta%
        \advance\c@pgf@counta by-1%
        \advance\c@pgf@countd by1%
        \divide\c@pgf@countc by\c@pgf@countd%
    \repeatpgfmathloop%
    \the\c@pgf@countc%
}
\makeatother

\begin{document} 
\begin{tikzpicture}
\foreach \n in {0,...,15} {
  \foreach \k in {0,...,\n} {
    \node at (\k-\n/2,-\n) {$\binomialCoefficient{\n}{\k}$};
  }
}
\end{tikzpicture}

\end{document}

在此处输入图片描述

如果您愿意,您可以围绕\pgfmathdeclarefunction它来使用 pgfmath 中的函数(参见手册(v2.10)中的第 65 节“自定义数学引擎”)。

答案2

摘自 texample.net。作者是 Paul Gaborit。

帕斯卡三角

在此处输入图片描述

答案3

第二个答案

先前的答案使用宏来计算单个二项式系数。

我现在讨论逐行构建帕斯卡三角形的问题,就像其他答案中提到的那样。

为了进行翻译练习,我复制了metapost@fpast 的代码回答,并将其翻译成 TeX。在第 34 行之前我们可以使用 TeX 算法。为简单起见,我使用了\numexpr。从第 34 行开始(实际上只有中间三个系数超过2^31-1),我使用大整数算法。

为了组织循环,我使用了\xintFor包中的xinttools。此包还定义了\odef哪些执行定义 + 扩展,\oodef哪些执行定义 + 双重扩展。它们在代码中与\numexpr\dimexpr\@namedef等的各种混合一起使用@nameuse……纯 TeX/LaTeX 有时会在允许或不允许空格的位置上表现出微妙的乐趣(大多数空格并不重要,因为我们在 TikZ 图片中)。

前 80 行代码的编译速度还不算太慢(在我的笔记本电脑上大约需要 9 秒)。

我只显示三角形的最大数字。

6cm请注意,我们接近 TeX 的最大尺寸限制,因为每个数字与其邻居水平分隔。

原始的 metapost 代码fpast与其 TeX 翻译版本一起显示。

编辑代码只测试了\numexpr前 33 行要使用的行号(因为只对整数<2^31进行求值),但实际上所有的计算都是用,xint而不是检查行号来决定使用的,\numexpr或者xint快点!(2%计算三角形的 80 条线时速度会快一些)。因此我注释掉了条件。

\documentclass[12pt, tikz, border=5mm]{standalone}
\usepackage{tikz}
\usepackage{xint}
\usepackage{xinttools}
\makeatletter
\newdimen\X
\newdimen\Y
\def\PascalTriangle #1#2#3{% #1=n (integer) #2=u (dimension) #3=v (dimension)
 %    save b, mid; numeric b[][], mid; clearxy;  
 %    b[0][0] = b[1][0] = b[1][1] = 1;
 %    label("1", origin); label("1", (-.5u, -v)); label("1", (.5u, -v));
    \edef\U {\the\numexpr\dimexpr #2\relax }% convert to sp units
    \edef\V {\the\numexpr\dimexpr #3\relax }%
    \@namedef{dali@0@0}{1}%
    \@namedef{dali@1@0}{1}%
    \@namedef{dali@0@1}{1}%
    \node at (0,0) {$1$};%
    \node at (-.5*#2,-#3) {$1$};
    \node at (.5*#2,-#3)  {$1$};
  % for i = 2 upto n:
    \xintFor ##1 in {\xintegers[2+1]}\do {%
    \ifnum #1<##1\expandafter\xintBreakFor\fi
  %        mid := i div 2;
          \odef\Mid  {\the\numexpr (##1+1)/2 -1\relax }%
  %       x := -u*i/2;
          \X = \dimexpr\the\numexpr (-##1*\U)/2\relax sp
  %       y := -i*v ;
          \Y = \dimexpr\the\numexpr -##1*\V\relax sp
  %       b[i][0] = 1; label("1", z); label("1", (-x, y));
          \@namedef{dali@\the##1@0}{1}%
          \node at (\X,\Y)  {$1$};
          \node at (-\X,\Y) {$1$};
  %       for k = 1 upto mid:
          \xintFor ##2 in {\xintegers[1+1]}\do {%
          \ifnum\Mid<##2\expandafter\xintBreakFor\fi
  %           x := x + u;
              \advance\X by #2\relax
              \let\next\@secondoftwo
  %           if (k < mid) or (odd i):
              \ifnum \Mid>##2\let\next\@firstoftwo\fi
              \ifodd      ##1\let\next\@firstoftwo\fi
              \next
            {%
  %               b[i][k] = b[i-1][k-1] + b[i-1][k]; 
  %          \ifnum ##1<34 % binomial coefficients are < 2^31
  %          % EDIT DROPS THIS CONDITIONAL
  %             \expandafter\odef\csname dali@\the##1@\the##2\endcsname
  %             {\the\numexpr\@nameuse{dali@\the\numexpr##1-1@\the\numexpr##2-1}
  %                         +\@nameuse{dali@\the\numexpr##1-1@\the##2}\relax }%
  %          \else % 34 choose 17 is 2333606220 > 2^31-1 = 2147483647
               \expandafter\oodef\csname dali@\the##1@\the##2\endcsname
               {\xintiiAdd{\@nameuse{dali@\the\numexpr##1-1@\the\numexpr##2-1}}
                          {\@nameuse{dali@\the\numexpr##1-1@\the##2}}}%
  %          \fi 
  %               label(decimal b[i][k], z); label(decimal b[i][k], (-x, y));
            \node at (\X,\Y)  {$\@nameuse{dali@\the##1@\the##2}$};
            \node at (-\X,\Y) {$\@nameuse{dali@\the##1@\the##2}$};
            }%
  %           else:
            {%
  %               b[i][k] = 2b[i-1][k-1];
  %          \ifnum ##1<34   % EDIT DROPS THIS CONDITIONAL
  %             \expandafter\odef\csname dali@\the##1@\the##2\endcsname
  %             {\the\numexpr2*\@nameuse{dali@\the\numexpr##1-1@\the\numexpr##2-1}\relax}%
  %          \else
               \expandafter\oodef\csname dali@\the##1@\the##2\endcsname
               {\xintDouble{\@nameuse{dali@\the\numexpr##1-1@\the\numexpr##2-1}}}%
  %          \fi 
  %               label(decimal b[i][k], z);
            \node at (\X,\Y) {$\@nameuse{dali@\the##1@\the##2}$};
            }%
  %           fi
  %       endfor
          }%
    % endfor
    }%
}
\makeatother

\begin{document}
\begin{tikzpicture}
   \PascalTriangle{80}{6cm}{1cm}
\end{tikzpicture}
\end{document}

二项式(80,40)附近的二项式系数


先前的答案

(计算单个二项式系数)

你可以这样做

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{tikz}


% \binomialb macro from https://tex.stackexchange.com/a/161863/4686
% expandably computes binomial coefficients with \numexpr

% START OF CODE
\catcode`_ 11

\def\binomialb #1#2{\romannumeral0\expandafter
    \binomialb_a\the\numexpr #1\expandafter.\the\numexpr #2.}

\def\binomialb_a #1.#2.{\expandafter\binomialb_b\the\numexpr #1-#2.#2.}

\def\binomialb_b #1.#2.{\ifnum #1<#2 \expandafter\binomialb_ca
                            \else   \expandafter\binomialb_cb
                            \fi {#1}{#2}}

\def\binomialb_ca #1{\ifnum#1=0 \expandafter \binomialb_one\else 
                    \expandafter \binomialb_d\fi {#1}}

\def\binomialb_cb #1#2{\ifnum #2=0 \expandafter\binomialb_one\else
                      \expandafter\binomialb_d\fi {#2}{#1}}

\def\binomialb_one #1#2{ 1}

\def\binomialb_d #1#2{\expandafter\binomialb_e \the\numexpr #2+1.#1!}

% n-k+1.k! -> u=n-k+2.v=2.w=n-k+1.k!
\def\binomialb_e #1.{\expandafter\binomialb_f \the\numexpr #1+1.2.#1.}

% u.v.w.k!
\def\binomialb_f #1.#2.#3.#4!%
{\ifnum #2>#4 \binomialb_end\fi
 \expandafter\binomialb_f
 \the\numexpr #1+1\expandafter.%
 \the\numexpr #2+1\expandafter.%
 \the\numexpr #1*#3/#2.#4!}

\def\binomialb_end #1*#2/#3!{\fi\space #2}
\catcode`_ 8
% END OR \binomialb code

\begin{document}\thispagestyle{empty}


\begin{tikzpicture}
\foreach \n in {0,...,4} {
  \foreach \k in {0,...,\n} {
    \node at (2*\k-\n,-\n) {${\n \choose \k} = \binomialb\n\k$};
  }
}
\end{tikzpicture}

\bigskip\bigskip

\begin{tikzpicture}
\foreach \n in {21,...,24} {
  \foreach \k in {10,...,\the\numexpr\n-11\relax} {
    \node at (3*\k-1.5*\n,-\n) {${\n \choose \k} = \binomialb\n\k$};
  }
}
\end{tikzpicture}


%\bigskip\bigskip

% arithmetic overflow, use xint and \binomialB !
% \begin{tikzpicture}
% \foreach \n in {30,...,34} {
%   \foreach \k in {15,...,\the\numexpr\n-15\relax} {
%     \node at (4*\k-2*\n,-\n) {${\n \choose \k} = \binomialb\n\k$};
%   }
% }
% \end{tikzpicture}

\end{document}

在此处输入图片描述

答案4

\documentclass[a4paper,12pt]{article}%
    \usepackage[dvipsnames]{xcolor} 
    \usepackage{tikz}
    \usepackage{pdfpages}
    \makeatletter
    \newcommand\binomialCoefficient[2]{%
        % Store values 
        \c@pgf@counta=#1% n
        \c@pgf@countb=#2% k
        %
        % Take advantage of symmetry if k > n - k
        \c@pgf@countc=\c@pgf@counta%
        \advance\c@pgf@countc by-\c@pgf@countb%
        \ifnum\c@pgf@countb>\c@pgf@countc%
            \c@pgf@countb=\c@pgf@countc%
        \fi%
        %
        % Recursively compute the coefficients
        \c@pgf@countc=1% will hold the result
        \c@pgf@countd=0% counter
        \pgfmathloop% c -> c*(n-i)/(i+1) for i=0,...,k-1
            \ifnum\c@pgf@countd<\c@pgf@countb%
            \multiply\c@pgf@countc by\c@pgf@counta%
            \advance\c@pgf@counta by-1%
            \advance\c@pgf@countd by1%
            \divide\c@pgf@countc by\c@pgf@countd%
        \repeatpgfmathloop%
        \the\c@pgf@countc%
    }
    \makeatother
    \begin{document}
    \begin{center} 
    \newdimen\R
    \R=.4cm
    \newcommand\mycolor{gray}
    \begin{tikzpicture}[line width=.8pt]
    \foreach \k in {0,...,12}{
        \begin{scope}[shift={(-60:{sqrt(3)*\R*\k})}]
         \pgfmathtruncatemacro\ystart{12-\k}
          \foreach \n in {0,...,\ystart}{
            \pgfmathtruncatemacro\newn{\n+\k}
            \ifthenelse{\k=0}{\def\mycolor{pink}}{}
            \ifthenelse{\k=1}{\def\mycolor{yellow}}{}
            \ifthenelse{\k=2}{\def\mycolor{blue}}{}
            \ifthenelse{\k=3}{\def\mycolor{green}}{}
            \ifthenelse{\k=8 \AND \n < 4}{\def\mycolor{purple}}{}
            \ifthenelse{\k=9 \AND \n = 3}{\def\mycolor{purple}}{}
            \begin{scope}[shift={(-120:{sqrt(3)*\R*\n})}]
               \draw[top color=\mycolor!20,bottom color=\mycolor!60] 
          (30:\R) \foreach \x in {90,150,...,330} {
                    -- (\x:\R)}
                    --cycle (90:0) node {\tiny $\mathbf{\binomialCoefficient{\newn}{\k}}$};
             \end{scope}
           }
         \end{scope}
    }
    \end{tikzpicture} 
    \end{center} 
    \end{document}

在此处输入图片描述

相关内容