combination function in python
Steven D'Aprano
steve at REMOVE.THIS.cybersource.com.au
Sun Apr 15 06:48:07 EDT 2007
On Sun, 15 Apr 2007 02:38:31 -0700, bearophileHUGS wrote:
> DanielJohnson:
>> Please help, I couldnt find the function through help.
>
> You can't find it because it's not there:
>
> def factorial(n):
> """factorial(n): return the factorial of the integer n.
> factorial(0) = 1
> factorial(n) with n<0 is -factorial(abs(n))
> """
> result = 1
> for i in xrange(1, abs(n)+1):
> result *= i
> if n >= 0:
> return result
> else:
> return -result
>
> def binomial(n, k):
> """binomial(n, k): return the binomial coefficient (n k)."""
> assert n>0 and isinstance(n, (int, long)) and isinstance(k, (int,
> long))
> if k < 0 or k > n:
> return 0
> if k == 0 or k == n:
> return 1
> return factorial(n) // (factorial(k) * factorial(n-k))
That's a naive and slow implementation. For even quite small values of n
and k, you end up generating some seriously big long ints, and then have
to (slowly!) divide them.
A better implementation would be something like this:
def binomial(n, k):
if not 0 <= k <= n:
return 0
if k == 0 or k == n:
return 1
# calculate n!/k! as one product, avoiding factors that
# just get canceled
P = k+1
for i in xrange(k+2, n+1):
P *= i
# if you are paranoid:
# C, rem = divmod(P, factorial(n-k))
# assert rem == 0
# return C
return P//factorial(n-k)
There's probably even a really clever way to avoid that final division,
but I suspect that would cost more in time and memory than it would save.
--
Steven.
More information about the Python-list
mailing list