2

How is it possible to evaluate complex formulas like

\binom{2^{4}-3}{2^3}

with

\pgfmathtruncatemacro

? I want this to evaluate to 1287.

What already works:

\begin{tikzpicture} 
\foreach  \l  in {2,4,8} {
\pgfmathtruncatemacro{\jn}{(2^\l)*\l}
\node[] at (\l,0) {$\jn$};
}
\end{tikzpicture}

Evaluates to 8, 64 and 2048

EDIT: An alternative would suit me as well.

1
1

You could use bigintcalc:

\documentclass{article}
\usepackage{bigintcalc}

\newcommand{\bigintcalcBinomial}[2]{%
  \bigintcalcDiv
    {\bigintcalcFac{#1}}
    {%
     \bigintcalcMul
       {\bigintcalcFac{#2}}
       {\bigintcalcFac{\bigintcalcSub{#1}{#2}}}%
    }%
}

\begin{document}

\bigintcalcBinomial{\bigintcalcSub{\bigintcalcPow{2}{4}}{3}}{\bigintcalcPow{2}{3}}

\end{document}

This prints

1287

0
5

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}.

Blockquote

3
  • This looks nice but I get an error \binom already defined. The other solution already helped me to solved. Nevertheless thank you very much for the detailed explanation and help! – user92048 Nov 26 '15 at 14:59
  • Glad that you solved your problem ;-) . The choice of macro name is up to you, I mistakendly used \binom but naturally this may be defined by packages, particularly amsmath. – user4686 Nov 26 '15 at 17:09
  • I have implemented binomial in dev version of xint. Currently about 5x--7x faster than using the factorial as here in the answer. Tested for things like \binom {200}{100} or \binom {500}{250}. – user4686 Nov 28 '15 at 16:22
4

You can use the powerful apnum macros.

 \documentclass{article}

 \input apnum

 \def\binom#1#2{{\evaldef\n {#1} \evaldef\k {#2}%
 \evaldef\X {\FAC{\n}/(\FAC{\k}*\FAC{\n-\k})}\X}}

 \begin{document}

 \binom{2^4-3}{2^3}

 \end{document}

Note that apnum can also be used in plain TeX, because it does use only TeX primitives. (And also note the joke message that appears on your terminal if you use it with LaTeX.)

2
  • so far LaTeX allows you to use the TeX primitives. Thus, take out the bye, insert this in the body of a LaTeX source, and you are done. Didn't you know that already ? ... – user4686 Nov 26 '15 at 18:10
  • @jfbu No, I didn't know it, because I'm not a LaTeX user. I edit the answer, thank's – User Nov 26 '15 at 18:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.