nchoosek(n, k) function, permitted scalar values for n and k arguments

Asked by Tomy Duby

Tomy Duby (view profile)

on 4 Oct 2015
Latest activity Edited by John D'Errico

John D'Errico (view profile)

on 5 Oct 2015
The R2015b (and older) Matlab documentation says that when n and k are scalars, they can be real and non-negative. However, for non-integer n I get the following result:
>> nchoosek(4.5, 2)
ans = Empty matrix: 0-by-2
>>
The correct answer is 4.5 * 3.5 / (1 * 2) = 7.8750. Am I doing something wrong?
Tomy

Products

Answer by John D'Errico

John D'Errico (view profile)

on 4 Oct 2015
Edited by John D'Errico

John D'Errico (view profile)

on 4 Oct 2015

You can choose to define that operator in ANY way you like.
However, if you had bothered to read the help for nchoosek, you would have found this:
nchoosek Binomial coefficient or all combinations.
nchoosek(N,K) where N and K are non-negative integers returns N!/K!(N-K)!.
So to call your answer the correct answer is not at all correct. In fact, since nchoosek is defined as a classic binomial coefficient, your answer is not even "correct" in any sense, since factorials are not defined for non-integer input. But suppose we chose to use the gamma function to extend those factorials to allow non-integer input?
Classically, the binomial coefficient is defined as
nchoosek(N,K) = factorial(N)/(factorial(K)*factorial(N-K))
Lets rewrite this using the relation between factorial and the gamma function.
factorial(m) = gamma(m+1)
So now technically, your case would have
gamma(5.5)./gamma(2)/gamma(3)
ans =
26.171
Completely irrelevant as I said, since binomial coefficients are generally undefined for non-integer input. I can see what you did for the non-integer case. The reason why binomial coefficients are often written in the form they are is because some of the terms in the factorials cancel out in that fraction. That would not work in any case for non-integers.
I'll add that the documentation does indicate that N may be any general real, non-negative values. But that only applies when N is a vector. In the case where N is a vector, nchoosek actually generates all possible combinations of those N elements, taken K at a time.
nchoosek([1.1 2.2 3.3],2)
ans =
1.1 2.2
1.1 3.3
2.2 3.3
Admittedly, the documentation should be clearer here, to distinguish the case where N is a scalar.
I hope the documentation folks are listening in to this one.

Tomy Duby

Tomy Duby (view profile)

on 5 Oct 2015
John,
Thanks for your prompt answer. I am sorry to say but I think that you are wrong in several details: First using
factorial(n) = gamma(n+1)
the correct expression for
nchoose(4.5, 2)
is
nchoose(4.5, 2) = factorial(4.5) / (factorial(2.5) * factorial(2)) =
gamma(4.5+1) / (gamma(2.5+1) * gamma(2+1)) = ... = 7.8750
Second, you are wrong that the binomial coefficient is not defined for non-integer inputs. There is a generalization of the binomial coefficient to the case when n is a non-integer, see, for example, https://en.wikipedia.org/wiki/Binomial_coefficient#Generalization_and_connection_to_the_binomial_series. You will find this useful when trying to expand (1+x)^p into a Taylor series where p is not an integer. In fact, it may also be negative.
The cancellation you mention works even when n is not an integer as long as k is an integer. For example
nchoosek(4, 2) = 4 * 3 / (1 * 2) = 6
nchoosek(5, 2) = 5 * 4 / (1 * 2) = 10
nchoosek(4.5, 2) = 4.5 * 3.5 / (1 * 2) = 7.875
What I completely agree with you that something is wrong with the documentation.
Sorry Tomy
John D'Errico

John D'Errico (view profile)

on 5 Oct 2015
You are wrong that nchoosek should be defined for non-integer inputs. It is what it is, and what the documentation says it is. That someone has chosen to define binomial coefficients for non-integer arguments is not completely relevant.
help nchoosek
That states very clearly that it expects integer inputs for N and K scalar.
Sadly, the doc for nchoosek is somewhat ambiguous. I've asked that this be forwarded to the documentation team to resolve the issue. Part of me wonders whether this might be a gradual move to allow non-integer scalar input, or if it was just sloppy documentation. My guess is the latter.