This
constexpr inline size_t binom(size_t n, size_t k) noexcept
{
return
( k> n )? 0 : // out of range
(k==0 || k==n )? 1 : // edge
(k==1 || k==n-1)? n : // first
( k+k < n )? // recursive:
(binom(n-1,k-1) * n)/k : // path to k=1 is faster
(binom(n-1,k) * n)/(n-k); // path to k=n-1 is faster
}
requires O(min{k,n-k}) operations, is reliable and can be done at compile time.
Explanation The binomial coefficients are defined as B(n,k)=k!(n-k)!/n!
, from which we see that B(n,k)=B(n,n-k)
. We can also obtain the recurrence relations n*B(n,k)=(n-k)*B(n-1,k)=k*B(n-1,k-1)
. Moreover, the result is trivial for k=0,1,n,n-1
.
For k=2
, the result is also trivially (n*(n-1))/2
.
Of course, you can do that also with other integer types. If you need to know a binomial coefficient which exceeds the largest representable integer type, you must use approximate methods: using double
instead. In this case, using the gamma function is preferrable
#include <cmath>
inline double logbinom(double n, double k) noexcept
{
return std::lgamma(n+1)-std::lgamma(n-k+1)-std::lgamma(k+1);
}
inline double binom(double n, double k) noexcept
{
return std::exp(logbinom(n,k));
}