xint
should have a binomial function but I forgot to include it in the last release.
Here is one way in the meantime:
The update has permuted the order of presentation, as testing proved that the simpler approach using the built-in factorial was significantly faster except for cases with a small #2
.
\documentclass{article}
\usepackage{xintexpr}% at least version 1.1 from 10/2014
% I used \binom but it is defined for typesetting by amsmath
\newcommand*\MyBinom[2]
{\xinttheexpr subs(subs(x!//y!//(x-y)!,y=#2), x=#1)\relax }
% the "subs" are there to evaluate only once the #1 and #2 which might
% be themselves expressions.
\begin{document}
\MyBinom{2^{4}-3}{2^3}
\xintFor* #1 in {\xintSeq {0}{50}}\do {\MyBinom{50}{#1}\xintifForLast{\par}{, }}
\end{document}
In case #1
is big and #2
relatively small (or is close to #1
), it is dispendious to compute possibly very big factorials.
For a related answer which does it only using \numexpr
(if it is possible to avoid overflow), see the answers to that question
Factorial (or, even better, binomial coefficient) function
Here is a definition using the syntax allowed by xintexpr
, which will do much less computations in the case of a small #2
(or a #2
close to #1
). However, it requires big #1
's (for example #1=200, #2=10
) for these alternatives to prove faster. They use the good approach but this approach must be coded directly to become competitive with the already built-in factorial.
I have incorporated to them a check for the range of the inputs. But they do not check if the inputs are integers (the macro above uses the factorial which truncates to an integer its argument before proceeding farther).
\newcommand*\MyBinom[2]
{\xinttheexpr subs(subs(subs(
(0 <= y && y <= x)?{(z=0)?{1}{iter(1; (@*(x-k+1))//k, k=1..z)}}{0},
z=(2y<=x)?{y}{x-y}), y=#2), x=#1)\relax }
Here is an alternative. The k++
construct uses less memory. But my testing showed the macro using it to be slower (I guess from all the k>z
tests which do not know we are using small integers only).
\newcommand*\MyBinom[2]
{\xinttheexpr subs(subs(subs(
(0 <= y && y <= x)?{(z=0)?{1}{iter(1; (k>z)?{abort}{@*(x-k+1)//k}, k=1++)}}{0},
z=(2y<=x)?{y}{x-y}), y=#2), x=#1)\relax }
In the future the package will surely have a binomial
function and probably also an \xintBinomial
macro. They will surely, as in the alternatives above, avoid compute big factorials to divide them later.
I forgot to say that all theses things are purely expandable macros.
Naturally, as in both cases we use expressions, \binom{2^{4}-3}{2^3}
works out of the box, as would have \binom{3*37}{2^5-3^2}
.