我想排版帕斯卡三角形的顶部。为了得到带有二项式系数名称的三角形,即,{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}
先前的答案
(计算单个二项式系数)
你可以这样做
\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}