Python Binomial Coefficient
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
import math
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
if y == 1 or y == x:
print(1)
if y > x:
print(0)
else:
a = math.factorial(x)
b = math.factorial(y)
div = a // (b*(x-y))
print(div)
This binomial coeeficient program works but when i input two of the same number which is supposed to equal to 1 or when y is greater than x it is supposed to equal to 0. the program needs a little tweaking if someone can please help me
python python-3.x
|
show 4 more comments
import math
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
if y == 1 or y == x:
print(1)
if y > x:
print(0)
else:
a = math.factorial(x)
b = math.factorial(y)
div = a // (b*(x-y))
print(div)
This binomial coeeficient program works but when i input two of the same number which is supposed to equal to 1 or when y is greater than x it is supposed to equal to 0. the program needs a little tweaking if someone can please help me
python python-3.x
1
What do you need help with? The formula you're using for binomial coefficients doesn't look quite right, is that it?
– Joni
Oct 25 '14 at 8:53
why you are usingwhile
? you can merely useif
!!
– Kasrâmvd
Oct 25 '14 at 8:55
when I input a number greater than x it comes up with an error or if x and y are equal to each other
– user3396351
Oct 25 '14 at 8:56
Enter a value for x: 1 Enter a value for y: 1 1 Traceback (most recent call last): File "D:CE151 Computer Programmingass1.py", line 122, in <module> elif len(line)==1 and "1"<=line<="8": exlist[int(line)]() File "D:CE151 Computer Programmingass1.py", line 83, in ex4 div = (a//(b*(x-y))) ZeroDivisionError: integer division or modulo by zero
– user3396351
Oct 25 '14 at 8:57
can you say what you want to do actually ?
– Kasrâmvd
Oct 25 '14 at 8:57
|
show 4 more comments
import math
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
if y == 1 or y == x:
print(1)
if y > x:
print(0)
else:
a = math.factorial(x)
b = math.factorial(y)
div = a // (b*(x-y))
print(div)
This binomial coeeficient program works but when i input two of the same number which is supposed to equal to 1 or when y is greater than x it is supposed to equal to 0. the program needs a little tweaking if someone can please help me
python python-3.x
import math
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
if y == 1 or y == x:
print(1)
if y > x:
print(0)
else:
a = math.factorial(x)
b = math.factorial(y)
div = a // (b*(x-y))
print(div)
This binomial coeeficient program works but when i input two of the same number which is supposed to equal to 1 or when y is greater than x it is supposed to equal to 0. the program needs a little tweaking if someone can please help me
python python-3.x
python python-3.x
edited Apr 23 '17 at 15:39
PM 2Ring
44k441101
44k441101
asked Oct 25 '14 at 8:50
user3396351user3396351
107117
107117
1
What do you need help with? The formula you're using for binomial coefficients doesn't look quite right, is that it?
– Joni
Oct 25 '14 at 8:53
why you are usingwhile
? you can merely useif
!!
– Kasrâmvd
Oct 25 '14 at 8:55
when I input a number greater than x it comes up with an error or if x and y are equal to each other
– user3396351
Oct 25 '14 at 8:56
Enter a value for x: 1 Enter a value for y: 1 1 Traceback (most recent call last): File "D:CE151 Computer Programmingass1.py", line 122, in <module> elif len(line)==1 and "1"<=line<="8": exlist[int(line)]() File "D:CE151 Computer Programmingass1.py", line 83, in ex4 div = (a//(b*(x-y))) ZeroDivisionError: integer division or modulo by zero
– user3396351
Oct 25 '14 at 8:57
can you say what you want to do actually ?
– Kasrâmvd
Oct 25 '14 at 8:57
|
show 4 more comments
1
What do you need help with? The formula you're using for binomial coefficients doesn't look quite right, is that it?
– Joni
Oct 25 '14 at 8:53
why you are usingwhile
? you can merely useif
!!
– Kasrâmvd
Oct 25 '14 at 8:55
when I input a number greater than x it comes up with an error or if x and y are equal to each other
– user3396351
Oct 25 '14 at 8:56
Enter a value for x: 1 Enter a value for y: 1 1 Traceback (most recent call last): File "D:CE151 Computer Programmingass1.py", line 122, in <module> elif len(line)==1 and "1"<=line<="8": exlist[int(line)]() File "D:CE151 Computer Programmingass1.py", line 83, in ex4 div = (a//(b*(x-y))) ZeroDivisionError: integer division or modulo by zero
– user3396351
Oct 25 '14 at 8:57
can you say what you want to do actually ?
– Kasrâmvd
Oct 25 '14 at 8:57
1
1
What do you need help with? The formula you're using for binomial coefficients doesn't look quite right, is that it?
– Joni
Oct 25 '14 at 8:53
What do you need help with? The formula you're using for binomial coefficients doesn't look quite right, is that it?
– Joni
Oct 25 '14 at 8:53
why you are using
while
? you can merely use if
!!– Kasrâmvd
Oct 25 '14 at 8:55
why you are using
while
? you can merely use if
!!– Kasrâmvd
Oct 25 '14 at 8:55
when I input a number greater than x it comes up with an error or if x and y are equal to each other
– user3396351
Oct 25 '14 at 8:56
when I input a number greater than x it comes up with an error or if x and y are equal to each other
– user3396351
Oct 25 '14 at 8:56
Enter a value for x: 1 Enter a value for y: 1 1 Traceback (most recent call last): File "D:CE151 Computer Programmingass1.py", line 122, in <module> elif len(line)==1 and "1"<=line<="8": exlist[int(line)]() File "D:CE151 Computer Programmingass1.py", line 83, in ex4 div = (a//(b*(x-y))) ZeroDivisionError: integer division or modulo by zero
– user3396351
Oct 25 '14 at 8:57
Enter a value for x: 1 Enter a value for y: 1 1 Traceback (most recent call last): File "D:CE151 Computer Programmingass1.py", line 122, in <module> elif len(line)==1 and "1"<=line<="8": exlist[int(line)]() File "D:CE151 Computer Programmingass1.py", line 83, in ex4 div = (a//(b*(x-y))) ZeroDivisionError: integer division or modulo by zero
– user3396351
Oct 25 '14 at 8:57
can you say what you want to do actually ?
– Kasrâmvd
Oct 25 '14 at 8:57
can you say what you want to do actually ?
– Kasrâmvd
Oct 25 '14 at 8:57
|
show 4 more comments
10 Answers
10
active
oldest
votes
Your program will continue with the second if
statement in the case of y == x
, causing a ZeroDivisionError
. You need to make the statements mutually exclusive; the way to do that is to use elif
("else if") instead of if
:
import math
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
if y == x:
print(1)
elif y == 1: # see georg's comment
print(x)
elif y > x: # will be executed only if y != 1 and y != x
print(0)
else: # will be executed only if y != 1 and y != x and x <= y
a = math.factorial(x)
b = math.factorial(y)
c = math.factorial(x-y) # that appears to be useful to get the correct result
div = a // (b * c)
print(div)
Okay Okay I admit you're right lool thanks for your help
– user3396351
Oct 25 '14 at 9:20
1
if y == 1 or y == x:
is incorrect, by definition,C(x,1)=x
.
– georg
Oct 25 '14 at 10:08
@georg: Thanks, I hadn't gone to the trouble of checking whether the OP's calculations were correct. I hope it's better now.
– Tim Pietzcker
Oct 25 '14 at 10:42
add a comment |
This question is old but as it comes up high on search results I will point out that scipy
has two functions for computing the binomial coefficients:
scipy.special.binom()
scipy.special.comb()
import scipy.special
# the two give the same results
scipy.special.binom(10, 5)
# 252.0
scipy.special.comb(10, 5)
# 252.0
scipy.special.binom(300, 150)
# 9.375970277281882e+88
scipy.special.comb(300, 150)
# 9.375970277281882e+88
# ...but with `exact == True`
scipy.special.comb(10, 5, exact=True)
# 252
scipy.special.comb(300, 150, exact=True)
# 393759702772827452793193754439064084879232655700081358920472352712975170021839591675861424
Note that scipy.special.comb(exact=True)
uses Python integers, and therefore it can handle arbitrarily large results!
Speed-wise, the three versions give somewhat different results:
num = 300
%timeit [[scipy.special.binom(n, k) for k in range(n + 1)] for n in range(num)]
# 52.9 ms ± 107 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit [[scipy.special.comb(n, k) for k in range(n + 1)] for n in range(num)]
# 183 ms ± 814 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)each)
%timeit [[scipy.special.comb(n, k, exact=True) for k in range(n + 1)] for n in range(num)]
# 180 ms ± 649 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
(and for n = 300
, the binomial coefficients are too large to be represented correctly using float64
numbers, as shown above).
6
I'll just add a caution that scipy.special.binom returns a floating point approximation. This is good enough for most applications, but might not suffice for theoretical purposes.
– Dave Radcliffe
Jun 27 '16 at 1:30
3
Scipy also offers the comb function, which can be used to compute exact values.
– Joel Croteau
Dec 7 '17 at 1:39
add a comment |
Here's a version that actually uses the correct formula . :)
#! /usr/bin/env python
''' Calculate binomial coefficient xCy = x! / (y! (x-y)!)
'''
from math import factorial as fac
def binomial(x, y):
try:
binom = fac(x) // fac(y) // fac(x - y)
except ValueError:
binom = 0
return binom
#Print Pascal's triangle to test binomial()
def pascal(m):
for x in range(m + 1):
print([binomial(x, y) for y in range(x + 1)])
def main():
#input = raw_input
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
print(binomial(x, y))
if __name__ == '__main__':
#pascal(8)
main()
...
Here's an alternate version of binomial()
I wrote several years ago that doesn't use math.factorial()
, which didn't exist in old versions of Python. However, it returns 1 if r is not in range(0, n+1).
def binomial(n, r):
''' Binomial coefficient, nCr, aka the "choose" function
n! / (r! * (n - r)!)
'''
p = 1
for i in range(1, min(r, n - r) + 1):
p *= n
p //= i
n -= 1
return p
Bah, who cares if the formula is correct. As long as my code doesn't throw any exceptions, it's fine, right? Right? :)
– Tim Pietzcker
Oct 25 '14 at 9:50
@TimPietzcker Hey, it's not your fault if the customer gives you the wrong specs for the software they want you to write for them. :)
– PM 2Ring
Oct 25 '14 at 9:52
2
Your (second) code seems to work with integer division as well, which is a great feature, since for n greater than (around) 60, floats start to give uncorrect results due to precision errors.
– mmj
Jun 5 '16 at 14:57
Here's a question asking about a less efficient recursive implementation: stackoverflow.com/questions/54932096/…
– John
Feb 28 at 19:05
add a comment |
So, this question comes up first if you search for "Implement binomial coefficients in Python". Only this answer in its second part contains an efficient implementation which relies on the multiplicative formula. This formula performs the bare minimum number of multiplications. The function below does not depend on any built-ins or imports:
def fcomb0(n, k):
'''
Compute the number of ways to choose $k$ elements out of a pile of $n.$
Use an iterative approach with the multiplicative formula:
$$frac{n!}{k!(n - k)!} =
frac{n(n - 1)dots(n - k + 1)}{k(k-1)dots(1)} =
prod_{i = 1}^{k}frac{n + 1 - i}{i}$$
Also rely on the symmetry: $C_n^k = C_n^{n - k},$ so the product can
be calculated up to $min(k, n - k).$
:param n: the size of the pile of elements
:param k: the number of elements to take from the pile
:return: the number of ways to choose k elements out of a pile of n
'''
# When k out of sensible range, should probably throw an exception.
# For compatibility with scipy.special.{comb, binom} returns 0 instead.
if k < 0 or k > n:
return 0
if k == 0 or k == n:
return 1
total_ways = 1
for i in range(min(k, n - k)):
total_ways = total_ways * (n - i) // (i + 1)
return total_ways
Finally, if you need even larger values and do not mind trading some accuracy, Stirling's approximation is probably the way to go.
add a comment |
For Python 3, scipy has the function scipy.special.comb, which may produce floating point as well as exact integer results
import scipy.special
res = scipy.special.comb(x, y, exact=True)
See the documentation for scipy.special.comb.
For Python 2, the function is located in scipy.misc, and it works the same way:
import scipy.misc
res = scipy.misc.comb(x, y, exact=True)
add a comment |
What about this one? :) It uses correct formula, avoids math.factorial
and takes less multiplication operations:
import math
import operator
product = lambda m,n: reduce(operator.mul, xrange(m, n+1), 1)
x = max(0, int(input("Enter a value for x: ")))
y = max(0, int(input("Enter a value for y: ")))
print product(y+1, x) / product(1, x-y)
Also, in order to avoid big-integer arithmetics you may use floating point numbers, convert
product(a[i])/product(b[i])
to product(a[i]/b[i])
and rewrite the above program as:
import math
import operator
product = lambda iterable: reduce(operator.mul, iterable, 1)
x = max(0, int(input("Enter a value for x: ")))
y = max(0, int(input("Enter a value for y: ")))
print product(map(operator.truediv, xrange(y+1, x+1), xrange(1, x-y+1)))
Why is avoidingmath.factorial
an advantage?
– BartoszKP
Oct 25 '14 at 9:48
@BartoszKP: May be it is not, but @pm-2ring in his answer pointed out thatmath.factorial
doesn't exist in old Pythons, so I desided to avoid it just for fun. Anyway, I've definedproduct
.
– firegurafiku
Oct 25 '14 at 9:53
@BartoszKP and firegurafiku :math.factorial()
is running at C speed so it's probably much faster than solutions that use Python loops. OTOH, factorial() grows very quickly: factorial(13) is too big to fit into anint
, so the much slowerlong
arithmetic must be used. firegurafiku's algorithm is better on that score than the simple factorial-based algorithm, but it still ends up working with large numbers. Continued in next comment...
– PM 2Ring
Oct 25 '14 at 11:40
1
@BartoszKP and firegurafiku : My loop-based version is the usual way to do it in languages that don't have big integers because the division in each loop keeps the cumulative value as small as possible. Also, by usingmin(r, n - r)
it does the minimum number of loops.
– PM 2Ring
Oct 25 '14 at 11:40
add a comment |
Here is a function that recursively calculates the binomial coefficients using conditional expressions
def binomial(n,k):
return 1 if k==0 else (0 if n==0 else binomial(n-1, k) + binomial(n-1, k-1))
add a comment |
I recommend using dynamic programming (DP) for computing binomial coefficients. In contrast to direct computation, it avoids multiplication and division of large numbers. In addition to recursive solution, it stores previously solved overlapping sub-problems in a table for fast look-up. The code below shows bottom-up (tabular) DP and top-down (memoized) DP implementations for computing binomial coefficients.
def binomial_coeffs1(n, k):
#top down DP
if (k == 0 or k == n):
return 1
if (memo[n][k] != -1):
return memo[n][k]
memo[n][k] = binomial_coeffs1(n-1, k-1) + binomial_coeffs1(n-1, k)
return memo[n][k]
def binomial_coeffs2(n, k):
#bottom up DP
for i in range(n+1):
for j in range(min(i,k)+1):
if (j == 0 or j == i):
memo[i][j] = 1
else:
memo[i][j] = memo[i-1][j-1] + memo[i-1][j]
#end if
#end for
#end for
return memo[n][k]
def print_array(memo):
for i in range(len(memo)):
print('t'.join([str(x) for x in memo[i]]))
#main
n = 5
k = 2
print("top down DP")
memo = [[-1 for i in range(6)] for j in range(6)]
nCk = binomial_coeffs1(n, k)
print_array(memo)
print("C(n={}, k={}) = {}".format(n,k,nCk))
print("bottom up DP")
memo = [[-1 for i in range(6)] for j in range(6)]
nCk = binomial_coeffs2(n, k)
print_array(memo)
print("C(n={}, k={}) = {}".format(n,k,nCk))
Note: the size of the memo table is set to a small value (6) for display purposes, it should be increased if you are computing binomial coefficients for large n and k.
add a comment |
It's a good idea to apply a recursive definition, as in Vadim Smolyakov's answer, combined with a DP (dynamic programming), but for the latter you may apply the lru_cache decorator from module functools:
import functools
@functools.lru_cache(maxsize = None)
def binom(n,k):
if k == 0: return 1
if n == k: return 1
return binom(n-1,k-1)+binom(n-1,k)
add a comment |
The simplest way is using the Multiplicative formula. It works for (n,n) and (n,0) as expected.
def coefficient(n,k):
c = 1.0
for i in range(1, k+1):
c *= float((n+1-i))/float(i)
return c
Multiplicative formula
New contributor
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f26560726%2fpython-binomial-coefficient%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
10 Answers
10
active
oldest
votes
10 Answers
10
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your program will continue with the second if
statement in the case of y == x
, causing a ZeroDivisionError
. You need to make the statements mutually exclusive; the way to do that is to use elif
("else if") instead of if
:
import math
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
if y == x:
print(1)
elif y == 1: # see georg's comment
print(x)
elif y > x: # will be executed only if y != 1 and y != x
print(0)
else: # will be executed only if y != 1 and y != x and x <= y
a = math.factorial(x)
b = math.factorial(y)
c = math.factorial(x-y) # that appears to be useful to get the correct result
div = a // (b * c)
print(div)
Okay Okay I admit you're right lool thanks for your help
– user3396351
Oct 25 '14 at 9:20
1
if y == 1 or y == x:
is incorrect, by definition,C(x,1)=x
.
– georg
Oct 25 '14 at 10:08
@georg: Thanks, I hadn't gone to the trouble of checking whether the OP's calculations were correct. I hope it's better now.
– Tim Pietzcker
Oct 25 '14 at 10:42
add a comment |
Your program will continue with the second if
statement in the case of y == x
, causing a ZeroDivisionError
. You need to make the statements mutually exclusive; the way to do that is to use elif
("else if") instead of if
:
import math
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
if y == x:
print(1)
elif y == 1: # see georg's comment
print(x)
elif y > x: # will be executed only if y != 1 and y != x
print(0)
else: # will be executed only if y != 1 and y != x and x <= y
a = math.factorial(x)
b = math.factorial(y)
c = math.factorial(x-y) # that appears to be useful to get the correct result
div = a // (b * c)
print(div)
Okay Okay I admit you're right lool thanks for your help
– user3396351
Oct 25 '14 at 9:20
1
if y == 1 or y == x:
is incorrect, by definition,C(x,1)=x
.
– georg
Oct 25 '14 at 10:08
@georg: Thanks, I hadn't gone to the trouble of checking whether the OP's calculations were correct. I hope it's better now.
– Tim Pietzcker
Oct 25 '14 at 10:42
add a comment |
Your program will continue with the second if
statement in the case of y == x
, causing a ZeroDivisionError
. You need to make the statements mutually exclusive; the way to do that is to use elif
("else if") instead of if
:
import math
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
if y == x:
print(1)
elif y == 1: # see georg's comment
print(x)
elif y > x: # will be executed only if y != 1 and y != x
print(0)
else: # will be executed only if y != 1 and y != x and x <= y
a = math.factorial(x)
b = math.factorial(y)
c = math.factorial(x-y) # that appears to be useful to get the correct result
div = a // (b * c)
print(div)
Your program will continue with the second if
statement in the case of y == x
, causing a ZeroDivisionError
. You need to make the statements mutually exclusive; the way to do that is to use elif
("else if") instead of if
:
import math
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
if y == x:
print(1)
elif y == 1: # see georg's comment
print(x)
elif y > x: # will be executed only if y != 1 and y != x
print(0)
else: # will be executed only if y != 1 and y != x and x <= y
a = math.factorial(x)
b = math.factorial(y)
c = math.factorial(x-y) # that appears to be useful to get the correct result
div = a // (b * c)
print(div)
edited Oct 25 '14 at 10:43
answered Oct 25 '14 at 9:19
Tim PietzckerTim Pietzcker
252k43381462
252k43381462
Okay Okay I admit you're right lool thanks for your help
– user3396351
Oct 25 '14 at 9:20
1
if y == 1 or y == x:
is incorrect, by definition,C(x,1)=x
.
– georg
Oct 25 '14 at 10:08
@georg: Thanks, I hadn't gone to the trouble of checking whether the OP's calculations were correct. I hope it's better now.
– Tim Pietzcker
Oct 25 '14 at 10:42
add a comment |
Okay Okay I admit you're right lool thanks for your help
– user3396351
Oct 25 '14 at 9:20
1
if y == 1 or y == x:
is incorrect, by definition,C(x,1)=x
.
– georg
Oct 25 '14 at 10:08
@georg: Thanks, I hadn't gone to the trouble of checking whether the OP's calculations were correct. I hope it's better now.
– Tim Pietzcker
Oct 25 '14 at 10:42
Okay Okay I admit you're right lool thanks for your help
– user3396351
Oct 25 '14 at 9:20
Okay Okay I admit you're right lool thanks for your help
– user3396351
Oct 25 '14 at 9:20
1
1
if y == 1 or y == x:
is incorrect, by definition, C(x,1)=x
.– georg
Oct 25 '14 at 10:08
if y == 1 or y == x:
is incorrect, by definition, C(x,1)=x
.– georg
Oct 25 '14 at 10:08
@georg: Thanks, I hadn't gone to the trouble of checking whether the OP's calculations were correct. I hope it's better now.
– Tim Pietzcker
Oct 25 '14 at 10:42
@georg: Thanks, I hadn't gone to the trouble of checking whether the OP's calculations were correct. I hope it's better now.
– Tim Pietzcker
Oct 25 '14 at 10:42
add a comment |
This question is old but as it comes up high on search results I will point out that scipy
has two functions for computing the binomial coefficients:
scipy.special.binom()
scipy.special.comb()
import scipy.special
# the two give the same results
scipy.special.binom(10, 5)
# 252.0
scipy.special.comb(10, 5)
# 252.0
scipy.special.binom(300, 150)
# 9.375970277281882e+88
scipy.special.comb(300, 150)
# 9.375970277281882e+88
# ...but with `exact == True`
scipy.special.comb(10, 5, exact=True)
# 252
scipy.special.comb(300, 150, exact=True)
# 393759702772827452793193754439064084879232655700081358920472352712975170021839591675861424
Note that scipy.special.comb(exact=True)
uses Python integers, and therefore it can handle arbitrarily large results!
Speed-wise, the three versions give somewhat different results:
num = 300
%timeit [[scipy.special.binom(n, k) for k in range(n + 1)] for n in range(num)]
# 52.9 ms ± 107 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit [[scipy.special.comb(n, k) for k in range(n + 1)] for n in range(num)]
# 183 ms ± 814 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)each)
%timeit [[scipy.special.comb(n, k, exact=True) for k in range(n + 1)] for n in range(num)]
# 180 ms ± 649 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
(and for n = 300
, the binomial coefficients are too large to be represented correctly using float64
numbers, as shown above).
6
I'll just add a caution that scipy.special.binom returns a floating point approximation. This is good enough for most applications, but might not suffice for theoretical purposes.
– Dave Radcliffe
Jun 27 '16 at 1:30
3
Scipy also offers the comb function, which can be used to compute exact values.
– Joel Croteau
Dec 7 '17 at 1:39
add a comment |
This question is old but as it comes up high on search results I will point out that scipy
has two functions for computing the binomial coefficients:
scipy.special.binom()
scipy.special.comb()
import scipy.special
# the two give the same results
scipy.special.binom(10, 5)
# 252.0
scipy.special.comb(10, 5)
# 252.0
scipy.special.binom(300, 150)
# 9.375970277281882e+88
scipy.special.comb(300, 150)
# 9.375970277281882e+88
# ...but with `exact == True`
scipy.special.comb(10, 5, exact=True)
# 252
scipy.special.comb(300, 150, exact=True)
# 393759702772827452793193754439064084879232655700081358920472352712975170021839591675861424
Note that scipy.special.comb(exact=True)
uses Python integers, and therefore it can handle arbitrarily large results!
Speed-wise, the three versions give somewhat different results:
num = 300
%timeit [[scipy.special.binom(n, k) for k in range(n + 1)] for n in range(num)]
# 52.9 ms ± 107 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit [[scipy.special.comb(n, k) for k in range(n + 1)] for n in range(num)]
# 183 ms ± 814 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)each)
%timeit [[scipy.special.comb(n, k, exact=True) for k in range(n + 1)] for n in range(num)]
# 180 ms ± 649 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
(and for n = 300
, the binomial coefficients are too large to be represented correctly using float64
numbers, as shown above).
6
I'll just add a caution that scipy.special.binom returns a floating point approximation. This is good enough for most applications, but might not suffice for theoretical purposes.
– Dave Radcliffe
Jun 27 '16 at 1:30
3
Scipy also offers the comb function, which can be used to compute exact values.
– Joel Croteau
Dec 7 '17 at 1:39
add a comment |
This question is old but as it comes up high on search results I will point out that scipy
has two functions for computing the binomial coefficients:
scipy.special.binom()
scipy.special.comb()
import scipy.special
# the two give the same results
scipy.special.binom(10, 5)
# 252.0
scipy.special.comb(10, 5)
# 252.0
scipy.special.binom(300, 150)
# 9.375970277281882e+88
scipy.special.comb(300, 150)
# 9.375970277281882e+88
# ...but with `exact == True`
scipy.special.comb(10, 5, exact=True)
# 252
scipy.special.comb(300, 150, exact=True)
# 393759702772827452793193754439064084879232655700081358920472352712975170021839591675861424
Note that scipy.special.comb(exact=True)
uses Python integers, and therefore it can handle arbitrarily large results!
Speed-wise, the three versions give somewhat different results:
num = 300
%timeit [[scipy.special.binom(n, k) for k in range(n + 1)] for n in range(num)]
# 52.9 ms ± 107 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit [[scipy.special.comb(n, k) for k in range(n + 1)] for n in range(num)]
# 183 ms ± 814 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)each)
%timeit [[scipy.special.comb(n, k, exact=True) for k in range(n + 1)] for n in range(num)]
# 180 ms ± 649 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
(and for n = 300
, the binomial coefficients are too large to be represented correctly using float64
numbers, as shown above).
This question is old but as it comes up high on search results I will point out that scipy
has two functions for computing the binomial coefficients:
scipy.special.binom()
scipy.special.comb()
import scipy.special
# the two give the same results
scipy.special.binom(10, 5)
# 252.0
scipy.special.comb(10, 5)
# 252.0
scipy.special.binom(300, 150)
# 9.375970277281882e+88
scipy.special.comb(300, 150)
# 9.375970277281882e+88
# ...but with `exact == True`
scipy.special.comb(10, 5, exact=True)
# 252
scipy.special.comb(300, 150, exact=True)
# 393759702772827452793193754439064084879232655700081358920472352712975170021839591675861424
Note that scipy.special.comb(exact=True)
uses Python integers, and therefore it can handle arbitrarily large results!
Speed-wise, the three versions give somewhat different results:
num = 300
%timeit [[scipy.special.binom(n, k) for k in range(n + 1)] for n in range(num)]
# 52.9 ms ± 107 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit [[scipy.special.comb(n, k) for k in range(n + 1)] for n in range(num)]
# 183 ms ± 814 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)each)
%timeit [[scipy.special.comb(n, k, exact=True) for k in range(n + 1)] for n in range(num)]
# 180 ms ± 649 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
(and for n = 300
, the binomial coefficients are too large to be represented correctly using float64
numbers, as shown above).
edited Aug 24 '18 at 18:49
norok2
2,84211532
2,84211532
answered Jul 15 '15 at 16:05
Shaun CouttsShaun Coutts
68152
68152
6
I'll just add a caution that scipy.special.binom returns a floating point approximation. This is good enough for most applications, but might not suffice for theoretical purposes.
– Dave Radcliffe
Jun 27 '16 at 1:30
3
Scipy also offers the comb function, which can be used to compute exact values.
– Joel Croteau
Dec 7 '17 at 1:39
add a comment |
6
I'll just add a caution that scipy.special.binom returns a floating point approximation. This is good enough for most applications, but might not suffice for theoretical purposes.
– Dave Radcliffe
Jun 27 '16 at 1:30
3
Scipy also offers the comb function, which can be used to compute exact values.
– Joel Croteau
Dec 7 '17 at 1:39
6
6
I'll just add a caution that scipy.special.binom returns a floating point approximation. This is good enough for most applications, but might not suffice for theoretical purposes.
– Dave Radcliffe
Jun 27 '16 at 1:30
I'll just add a caution that scipy.special.binom returns a floating point approximation. This is good enough for most applications, but might not suffice for theoretical purposes.
– Dave Radcliffe
Jun 27 '16 at 1:30
3
3
Scipy also offers the comb function, which can be used to compute exact values.
– Joel Croteau
Dec 7 '17 at 1:39
Scipy also offers the comb function, which can be used to compute exact values.
– Joel Croteau
Dec 7 '17 at 1:39
add a comment |
Here's a version that actually uses the correct formula . :)
#! /usr/bin/env python
''' Calculate binomial coefficient xCy = x! / (y! (x-y)!)
'''
from math import factorial as fac
def binomial(x, y):
try:
binom = fac(x) // fac(y) // fac(x - y)
except ValueError:
binom = 0
return binom
#Print Pascal's triangle to test binomial()
def pascal(m):
for x in range(m + 1):
print([binomial(x, y) for y in range(x + 1)])
def main():
#input = raw_input
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
print(binomial(x, y))
if __name__ == '__main__':
#pascal(8)
main()
...
Here's an alternate version of binomial()
I wrote several years ago that doesn't use math.factorial()
, which didn't exist in old versions of Python. However, it returns 1 if r is not in range(0, n+1).
def binomial(n, r):
''' Binomial coefficient, nCr, aka the "choose" function
n! / (r! * (n - r)!)
'''
p = 1
for i in range(1, min(r, n - r) + 1):
p *= n
p //= i
n -= 1
return p
Bah, who cares if the formula is correct. As long as my code doesn't throw any exceptions, it's fine, right? Right? :)
– Tim Pietzcker
Oct 25 '14 at 9:50
@TimPietzcker Hey, it's not your fault if the customer gives you the wrong specs for the software they want you to write for them. :)
– PM 2Ring
Oct 25 '14 at 9:52
2
Your (second) code seems to work with integer division as well, which is a great feature, since for n greater than (around) 60, floats start to give uncorrect results due to precision errors.
– mmj
Jun 5 '16 at 14:57
Here's a question asking about a less efficient recursive implementation: stackoverflow.com/questions/54932096/…
– John
Feb 28 at 19:05
add a comment |
Here's a version that actually uses the correct formula . :)
#! /usr/bin/env python
''' Calculate binomial coefficient xCy = x! / (y! (x-y)!)
'''
from math import factorial as fac
def binomial(x, y):
try:
binom = fac(x) // fac(y) // fac(x - y)
except ValueError:
binom = 0
return binom
#Print Pascal's triangle to test binomial()
def pascal(m):
for x in range(m + 1):
print([binomial(x, y) for y in range(x + 1)])
def main():
#input = raw_input
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
print(binomial(x, y))
if __name__ == '__main__':
#pascal(8)
main()
...
Here's an alternate version of binomial()
I wrote several years ago that doesn't use math.factorial()
, which didn't exist in old versions of Python. However, it returns 1 if r is not in range(0, n+1).
def binomial(n, r):
''' Binomial coefficient, nCr, aka the "choose" function
n! / (r! * (n - r)!)
'''
p = 1
for i in range(1, min(r, n - r) + 1):
p *= n
p //= i
n -= 1
return p
Bah, who cares if the formula is correct. As long as my code doesn't throw any exceptions, it's fine, right? Right? :)
– Tim Pietzcker
Oct 25 '14 at 9:50
@TimPietzcker Hey, it's not your fault if the customer gives you the wrong specs for the software they want you to write for them. :)
– PM 2Ring
Oct 25 '14 at 9:52
2
Your (second) code seems to work with integer division as well, which is a great feature, since for n greater than (around) 60, floats start to give uncorrect results due to precision errors.
– mmj
Jun 5 '16 at 14:57
Here's a question asking about a less efficient recursive implementation: stackoverflow.com/questions/54932096/…
– John
Feb 28 at 19:05
add a comment |
Here's a version that actually uses the correct formula . :)
#! /usr/bin/env python
''' Calculate binomial coefficient xCy = x! / (y! (x-y)!)
'''
from math import factorial as fac
def binomial(x, y):
try:
binom = fac(x) // fac(y) // fac(x - y)
except ValueError:
binom = 0
return binom
#Print Pascal's triangle to test binomial()
def pascal(m):
for x in range(m + 1):
print([binomial(x, y) for y in range(x + 1)])
def main():
#input = raw_input
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
print(binomial(x, y))
if __name__ == '__main__':
#pascal(8)
main()
...
Here's an alternate version of binomial()
I wrote several years ago that doesn't use math.factorial()
, which didn't exist in old versions of Python. However, it returns 1 if r is not in range(0, n+1).
def binomial(n, r):
''' Binomial coefficient, nCr, aka the "choose" function
n! / (r! * (n - r)!)
'''
p = 1
for i in range(1, min(r, n - r) + 1):
p *= n
p //= i
n -= 1
return p
Here's a version that actually uses the correct formula . :)
#! /usr/bin/env python
''' Calculate binomial coefficient xCy = x! / (y! (x-y)!)
'''
from math import factorial as fac
def binomial(x, y):
try:
binom = fac(x) // fac(y) // fac(x - y)
except ValueError:
binom = 0
return binom
#Print Pascal's triangle to test binomial()
def pascal(m):
for x in range(m + 1):
print([binomial(x, y) for y in range(x + 1)])
def main():
#input = raw_input
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
print(binomial(x, y))
if __name__ == '__main__':
#pascal(8)
main()
...
Here's an alternate version of binomial()
I wrote several years ago that doesn't use math.factorial()
, which didn't exist in old versions of Python. However, it returns 1 if r is not in range(0, n+1).
def binomial(n, r):
''' Binomial coefficient, nCr, aka the "choose" function
n! / (r! * (n - r)!)
'''
p = 1
for i in range(1, min(r, n - r) + 1):
p *= n
p //= i
n -= 1
return p
edited Nov 23 '18 at 14:26
answered Oct 25 '14 at 9:40
PM 2RingPM 2Ring
44k441101
44k441101
Bah, who cares if the formula is correct. As long as my code doesn't throw any exceptions, it's fine, right? Right? :)
– Tim Pietzcker
Oct 25 '14 at 9:50
@TimPietzcker Hey, it's not your fault if the customer gives you the wrong specs for the software they want you to write for them. :)
– PM 2Ring
Oct 25 '14 at 9:52
2
Your (second) code seems to work with integer division as well, which is a great feature, since for n greater than (around) 60, floats start to give uncorrect results due to precision errors.
– mmj
Jun 5 '16 at 14:57
Here's a question asking about a less efficient recursive implementation: stackoverflow.com/questions/54932096/…
– John
Feb 28 at 19:05
add a comment |
Bah, who cares if the formula is correct. As long as my code doesn't throw any exceptions, it's fine, right? Right? :)
– Tim Pietzcker
Oct 25 '14 at 9:50
@TimPietzcker Hey, it's not your fault if the customer gives you the wrong specs for the software they want you to write for them. :)
– PM 2Ring
Oct 25 '14 at 9:52
2
Your (second) code seems to work with integer division as well, which is a great feature, since for n greater than (around) 60, floats start to give uncorrect results due to precision errors.
– mmj
Jun 5 '16 at 14:57
Here's a question asking about a less efficient recursive implementation: stackoverflow.com/questions/54932096/…
– John
Feb 28 at 19:05
Bah, who cares if the formula is correct. As long as my code doesn't throw any exceptions, it's fine, right? Right? :)
– Tim Pietzcker
Oct 25 '14 at 9:50
Bah, who cares if the formula is correct. As long as my code doesn't throw any exceptions, it's fine, right? Right? :)
– Tim Pietzcker
Oct 25 '14 at 9:50
@TimPietzcker Hey, it's not your fault if the customer gives you the wrong specs for the software they want you to write for them. :)
– PM 2Ring
Oct 25 '14 at 9:52
@TimPietzcker Hey, it's not your fault if the customer gives you the wrong specs for the software they want you to write for them. :)
– PM 2Ring
Oct 25 '14 at 9:52
2
2
Your (second) code seems to work with integer division as well, which is a great feature, since for n greater than (around) 60, floats start to give uncorrect results due to precision errors.
– mmj
Jun 5 '16 at 14:57
Your (second) code seems to work with integer division as well, which is a great feature, since for n greater than (around) 60, floats start to give uncorrect results due to precision errors.
– mmj
Jun 5 '16 at 14:57
Here's a question asking about a less efficient recursive implementation: stackoverflow.com/questions/54932096/…
– John
Feb 28 at 19:05
Here's a question asking about a less efficient recursive implementation: stackoverflow.com/questions/54932096/…
– John
Feb 28 at 19:05
add a comment |
So, this question comes up first if you search for "Implement binomial coefficients in Python". Only this answer in its second part contains an efficient implementation which relies on the multiplicative formula. This formula performs the bare minimum number of multiplications. The function below does not depend on any built-ins or imports:
def fcomb0(n, k):
'''
Compute the number of ways to choose $k$ elements out of a pile of $n.$
Use an iterative approach with the multiplicative formula:
$$frac{n!}{k!(n - k)!} =
frac{n(n - 1)dots(n - k + 1)}{k(k-1)dots(1)} =
prod_{i = 1}^{k}frac{n + 1 - i}{i}$$
Also rely on the symmetry: $C_n^k = C_n^{n - k},$ so the product can
be calculated up to $min(k, n - k).$
:param n: the size of the pile of elements
:param k: the number of elements to take from the pile
:return: the number of ways to choose k elements out of a pile of n
'''
# When k out of sensible range, should probably throw an exception.
# For compatibility with scipy.special.{comb, binom} returns 0 instead.
if k < 0 or k > n:
return 0
if k == 0 or k == n:
return 1
total_ways = 1
for i in range(min(k, n - k)):
total_ways = total_ways * (n - i) // (i + 1)
return total_ways
Finally, if you need even larger values and do not mind trading some accuracy, Stirling's approximation is probably the way to go.
add a comment |
So, this question comes up first if you search for "Implement binomial coefficients in Python". Only this answer in its second part contains an efficient implementation which relies on the multiplicative formula. This formula performs the bare minimum number of multiplications. The function below does not depend on any built-ins or imports:
def fcomb0(n, k):
'''
Compute the number of ways to choose $k$ elements out of a pile of $n.$
Use an iterative approach with the multiplicative formula:
$$frac{n!}{k!(n - k)!} =
frac{n(n - 1)dots(n - k + 1)}{k(k-1)dots(1)} =
prod_{i = 1}^{k}frac{n + 1 - i}{i}$$
Also rely on the symmetry: $C_n^k = C_n^{n - k},$ so the product can
be calculated up to $min(k, n - k).$
:param n: the size of the pile of elements
:param k: the number of elements to take from the pile
:return: the number of ways to choose k elements out of a pile of n
'''
# When k out of sensible range, should probably throw an exception.
# For compatibility with scipy.special.{comb, binom} returns 0 instead.
if k < 0 or k > n:
return 0
if k == 0 or k == n:
return 1
total_ways = 1
for i in range(min(k, n - k)):
total_ways = total_ways * (n - i) // (i + 1)
return total_ways
Finally, if you need even larger values and do not mind trading some accuracy, Stirling's approximation is probably the way to go.
add a comment |
So, this question comes up first if you search for "Implement binomial coefficients in Python". Only this answer in its second part contains an efficient implementation which relies on the multiplicative formula. This formula performs the bare minimum number of multiplications. The function below does not depend on any built-ins or imports:
def fcomb0(n, k):
'''
Compute the number of ways to choose $k$ elements out of a pile of $n.$
Use an iterative approach with the multiplicative formula:
$$frac{n!}{k!(n - k)!} =
frac{n(n - 1)dots(n - k + 1)}{k(k-1)dots(1)} =
prod_{i = 1}^{k}frac{n + 1 - i}{i}$$
Also rely on the symmetry: $C_n^k = C_n^{n - k},$ so the product can
be calculated up to $min(k, n - k).$
:param n: the size of the pile of elements
:param k: the number of elements to take from the pile
:return: the number of ways to choose k elements out of a pile of n
'''
# When k out of sensible range, should probably throw an exception.
# For compatibility with scipy.special.{comb, binom} returns 0 instead.
if k < 0 or k > n:
return 0
if k == 0 or k == n:
return 1
total_ways = 1
for i in range(min(k, n - k)):
total_ways = total_ways * (n - i) // (i + 1)
return total_ways
Finally, if you need even larger values and do not mind trading some accuracy, Stirling's approximation is probably the way to go.
So, this question comes up first if you search for "Implement binomial coefficients in Python". Only this answer in its second part contains an efficient implementation which relies on the multiplicative formula. This formula performs the bare minimum number of multiplications. The function below does not depend on any built-ins or imports:
def fcomb0(n, k):
'''
Compute the number of ways to choose $k$ elements out of a pile of $n.$
Use an iterative approach with the multiplicative formula:
$$frac{n!}{k!(n - k)!} =
frac{n(n - 1)dots(n - k + 1)}{k(k-1)dots(1)} =
prod_{i = 1}^{k}frac{n + 1 - i}{i}$$
Also rely on the symmetry: $C_n^k = C_n^{n - k},$ so the product can
be calculated up to $min(k, n - k).$
:param n: the size of the pile of elements
:param k: the number of elements to take from the pile
:return: the number of ways to choose k elements out of a pile of n
'''
# When k out of sensible range, should probably throw an exception.
# For compatibility with scipy.special.{comb, binom} returns 0 instead.
if k < 0 or k > n:
return 0
if k == 0 or k == n:
return 1
total_ways = 1
for i in range(min(k, n - k)):
total_ways = total_ways * (n - i) // (i + 1)
return total_ways
Finally, if you need even larger values and do not mind trading some accuracy, Stirling's approximation is probably the way to go.
edited Oct 2 '18 at 22:31
Adrian Keister
258218
258218
answered Oct 16 '17 at 20:12
alisianoialisianoi
83011632
83011632
add a comment |
add a comment |
For Python 3, scipy has the function scipy.special.comb, which may produce floating point as well as exact integer results
import scipy.special
res = scipy.special.comb(x, y, exact=True)
See the documentation for scipy.special.comb.
For Python 2, the function is located in scipy.misc, and it works the same way:
import scipy.misc
res = scipy.misc.comb(x, y, exact=True)
add a comment |
For Python 3, scipy has the function scipy.special.comb, which may produce floating point as well as exact integer results
import scipy.special
res = scipy.special.comb(x, y, exact=True)
See the documentation for scipy.special.comb.
For Python 2, the function is located in scipy.misc, and it works the same way:
import scipy.misc
res = scipy.misc.comb(x, y, exact=True)
add a comment |
For Python 3, scipy has the function scipy.special.comb, which may produce floating point as well as exact integer results
import scipy.special
res = scipy.special.comb(x, y, exact=True)
See the documentation for scipy.special.comb.
For Python 2, the function is located in scipy.misc, and it works the same way:
import scipy.misc
res = scipy.misc.comb(x, y, exact=True)
For Python 3, scipy has the function scipy.special.comb, which may produce floating point as well as exact integer results
import scipy.special
res = scipy.special.comb(x, y, exact=True)
See the documentation for scipy.special.comb.
For Python 2, the function is located in scipy.misc, and it works the same way:
import scipy.misc
res = scipy.misc.comb(x, y, exact=True)
edited Jul 5 '17 at 19:25
answered Jul 5 '17 at 19:07
SlavaSlava
679412
679412
add a comment |
add a comment |
What about this one? :) It uses correct formula, avoids math.factorial
and takes less multiplication operations:
import math
import operator
product = lambda m,n: reduce(operator.mul, xrange(m, n+1), 1)
x = max(0, int(input("Enter a value for x: ")))
y = max(0, int(input("Enter a value for y: ")))
print product(y+1, x) / product(1, x-y)
Also, in order to avoid big-integer arithmetics you may use floating point numbers, convert
product(a[i])/product(b[i])
to product(a[i]/b[i])
and rewrite the above program as:
import math
import operator
product = lambda iterable: reduce(operator.mul, iterable, 1)
x = max(0, int(input("Enter a value for x: ")))
y = max(0, int(input("Enter a value for y: ")))
print product(map(operator.truediv, xrange(y+1, x+1), xrange(1, x-y+1)))
Why is avoidingmath.factorial
an advantage?
– BartoszKP
Oct 25 '14 at 9:48
@BartoszKP: May be it is not, but @pm-2ring in his answer pointed out thatmath.factorial
doesn't exist in old Pythons, so I desided to avoid it just for fun. Anyway, I've definedproduct
.
– firegurafiku
Oct 25 '14 at 9:53
@BartoszKP and firegurafiku :math.factorial()
is running at C speed so it's probably much faster than solutions that use Python loops. OTOH, factorial() grows very quickly: factorial(13) is too big to fit into anint
, so the much slowerlong
arithmetic must be used. firegurafiku's algorithm is better on that score than the simple factorial-based algorithm, but it still ends up working with large numbers. Continued in next comment...
– PM 2Ring
Oct 25 '14 at 11:40
1
@BartoszKP and firegurafiku : My loop-based version is the usual way to do it in languages that don't have big integers because the division in each loop keeps the cumulative value as small as possible. Also, by usingmin(r, n - r)
it does the minimum number of loops.
– PM 2Ring
Oct 25 '14 at 11:40
add a comment |
What about this one? :) It uses correct formula, avoids math.factorial
and takes less multiplication operations:
import math
import operator
product = lambda m,n: reduce(operator.mul, xrange(m, n+1), 1)
x = max(0, int(input("Enter a value for x: ")))
y = max(0, int(input("Enter a value for y: ")))
print product(y+1, x) / product(1, x-y)
Also, in order to avoid big-integer arithmetics you may use floating point numbers, convert
product(a[i])/product(b[i])
to product(a[i]/b[i])
and rewrite the above program as:
import math
import operator
product = lambda iterable: reduce(operator.mul, iterable, 1)
x = max(0, int(input("Enter a value for x: ")))
y = max(0, int(input("Enter a value for y: ")))
print product(map(operator.truediv, xrange(y+1, x+1), xrange(1, x-y+1)))
Why is avoidingmath.factorial
an advantage?
– BartoszKP
Oct 25 '14 at 9:48
@BartoszKP: May be it is not, but @pm-2ring in his answer pointed out thatmath.factorial
doesn't exist in old Pythons, so I desided to avoid it just for fun. Anyway, I've definedproduct
.
– firegurafiku
Oct 25 '14 at 9:53
@BartoszKP and firegurafiku :math.factorial()
is running at C speed so it's probably much faster than solutions that use Python loops. OTOH, factorial() grows very quickly: factorial(13) is too big to fit into anint
, so the much slowerlong
arithmetic must be used. firegurafiku's algorithm is better on that score than the simple factorial-based algorithm, but it still ends up working with large numbers. Continued in next comment...
– PM 2Ring
Oct 25 '14 at 11:40
1
@BartoszKP and firegurafiku : My loop-based version is the usual way to do it in languages that don't have big integers because the division in each loop keeps the cumulative value as small as possible. Also, by usingmin(r, n - r)
it does the minimum number of loops.
– PM 2Ring
Oct 25 '14 at 11:40
add a comment |
What about this one? :) It uses correct formula, avoids math.factorial
and takes less multiplication operations:
import math
import operator
product = lambda m,n: reduce(operator.mul, xrange(m, n+1), 1)
x = max(0, int(input("Enter a value for x: ")))
y = max(0, int(input("Enter a value for y: ")))
print product(y+1, x) / product(1, x-y)
Also, in order to avoid big-integer arithmetics you may use floating point numbers, convert
product(a[i])/product(b[i])
to product(a[i]/b[i])
and rewrite the above program as:
import math
import operator
product = lambda iterable: reduce(operator.mul, iterable, 1)
x = max(0, int(input("Enter a value for x: ")))
y = max(0, int(input("Enter a value for y: ")))
print product(map(operator.truediv, xrange(y+1, x+1), xrange(1, x-y+1)))
What about this one? :) It uses correct formula, avoids math.factorial
and takes less multiplication operations:
import math
import operator
product = lambda m,n: reduce(operator.mul, xrange(m, n+1), 1)
x = max(0, int(input("Enter a value for x: ")))
y = max(0, int(input("Enter a value for y: ")))
print product(y+1, x) / product(1, x-y)
Also, in order to avoid big-integer arithmetics you may use floating point numbers, convert
product(a[i])/product(b[i])
to product(a[i]/b[i])
and rewrite the above program as:
import math
import operator
product = lambda iterable: reduce(operator.mul, iterable, 1)
x = max(0, int(input("Enter a value for x: ")))
y = max(0, int(input("Enter a value for y: ")))
print product(map(operator.truediv, xrange(y+1, x+1), xrange(1, x-y+1)))
edited Oct 26 '14 at 11:24
answered Oct 25 '14 at 9:47
firegurafikufiregurafiku
1,6281726
1,6281726
Why is avoidingmath.factorial
an advantage?
– BartoszKP
Oct 25 '14 at 9:48
@BartoszKP: May be it is not, but @pm-2ring in his answer pointed out thatmath.factorial
doesn't exist in old Pythons, so I desided to avoid it just for fun. Anyway, I've definedproduct
.
– firegurafiku
Oct 25 '14 at 9:53
@BartoszKP and firegurafiku :math.factorial()
is running at C speed so it's probably much faster than solutions that use Python loops. OTOH, factorial() grows very quickly: factorial(13) is too big to fit into anint
, so the much slowerlong
arithmetic must be used. firegurafiku's algorithm is better on that score than the simple factorial-based algorithm, but it still ends up working with large numbers. Continued in next comment...
– PM 2Ring
Oct 25 '14 at 11:40
1
@BartoszKP and firegurafiku : My loop-based version is the usual way to do it in languages that don't have big integers because the division in each loop keeps the cumulative value as small as possible. Also, by usingmin(r, n - r)
it does the minimum number of loops.
– PM 2Ring
Oct 25 '14 at 11:40
add a comment |
Why is avoidingmath.factorial
an advantage?
– BartoszKP
Oct 25 '14 at 9:48
@BartoszKP: May be it is not, but @pm-2ring in his answer pointed out thatmath.factorial
doesn't exist in old Pythons, so I desided to avoid it just for fun. Anyway, I've definedproduct
.
– firegurafiku
Oct 25 '14 at 9:53
@BartoszKP and firegurafiku :math.factorial()
is running at C speed so it's probably much faster than solutions that use Python loops. OTOH, factorial() grows very quickly: factorial(13) is too big to fit into anint
, so the much slowerlong
arithmetic must be used. firegurafiku's algorithm is better on that score than the simple factorial-based algorithm, but it still ends up working with large numbers. Continued in next comment...
– PM 2Ring
Oct 25 '14 at 11:40
1
@BartoszKP and firegurafiku : My loop-based version is the usual way to do it in languages that don't have big integers because the division in each loop keeps the cumulative value as small as possible. Also, by usingmin(r, n - r)
it does the minimum number of loops.
– PM 2Ring
Oct 25 '14 at 11:40
Why is avoiding
math.factorial
an advantage?– BartoszKP
Oct 25 '14 at 9:48
Why is avoiding
math.factorial
an advantage?– BartoszKP
Oct 25 '14 at 9:48
@BartoszKP: May be it is not, but @pm-2ring in his answer pointed out that
math.factorial
doesn't exist in old Pythons, so I desided to avoid it just for fun. Anyway, I've defined product
.– firegurafiku
Oct 25 '14 at 9:53
@BartoszKP: May be it is not, but @pm-2ring in his answer pointed out that
math.factorial
doesn't exist in old Pythons, so I desided to avoid it just for fun. Anyway, I've defined product
.– firegurafiku
Oct 25 '14 at 9:53
@BartoszKP and firegurafiku :
math.factorial()
is running at C speed so it's probably much faster than solutions that use Python loops. OTOH, factorial() grows very quickly: factorial(13) is too big to fit into an int
, so the much slower long
arithmetic must be used. firegurafiku's algorithm is better on that score than the simple factorial-based algorithm, but it still ends up working with large numbers. Continued in next comment...– PM 2Ring
Oct 25 '14 at 11:40
@BartoszKP and firegurafiku :
math.factorial()
is running at C speed so it's probably much faster than solutions that use Python loops. OTOH, factorial() grows very quickly: factorial(13) is too big to fit into an int
, so the much slower long
arithmetic must be used. firegurafiku's algorithm is better on that score than the simple factorial-based algorithm, but it still ends up working with large numbers. Continued in next comment...– PM 2Ring
Oct 25 '14 at 11:40
1
1
@BartoszKP and firegurafiku : My loop-based version is the usual way to do it in languages that don't have big integers because the division in each loop keeps the cumulative value as small as possible. Also, by using
min(r, n - r)
it does the minimum number of loops.– PM 2Ring
Oct 25 '14 at 11:40
@BartoszKP and firegurafiku : My loop-based version is the usual way to do it in languages that don't have big integers because the division in each loop keeps the cumulative value as small as possible. Also, by using
min(r, n - r)
it does the minimum number of loops.– PM 2Ring
Oct 25 '14 at 11:40
add a comment |
Here is a function that recursively calculates the binomial coefficients using conditional expressions
def binomial(n,k):
return 1 if k==0 else (0 if n==0 else binomial(n-1, k) + binomial(n-1, k-1))
add a comment |
Here is a function that recursively calculates the binomial coefficients using conditional expressions
def binomial(n,k):
return 1 if k==0 else (0 if n==0 else binomial(n-1, k) + binomial(n-1, k-1))
add a comment |
Here is a function that recursively calculates the binomial coefficients using conditional expressions
def binomial(n,k):
return 1 if k==0 else (0 if n==0 else binomial(n-1, k) + binomial(n-1, k-1))
Here is a function that recursively calculates the binomial coefficients using conditional expressions
def binomial(n,k):
return 1 if k==0 else (0 if n==0 else binomial(n-1, k) + binomial(n-1, k-1))
edited Aug 19 '18 at 16:20
hoefling
13.8k43667
13.8k43667
answered May 10 '16 at 11:27
merraismerrais
32526
32526
add a comment |
add a comment |
I recommend using dynamic programming (DP) for computing binomial coefficients. In contrast to direct computation, it avoids multiplication and division of large numbers. In addition to recursive solution, it stores previously solved overlapping sub-problems in a table for fast look-up. The code below shows bottom-up (tabular) DP and top-down (memoized) DP implementations for computing binomial coefficients.
def binomial_coeffs1(n, k):
#top down DP
if (k == 0 or k == n):
return 1
if (memo[n][k] != -1):
return memo[n][k]
memo[n][k] = binomial_coeffs1(n-1, k-1) + binomial_coeffs1(n-1, k)
return memo[n][k]
def binomial_coeffs2(n, k):
#bottom up DP
for i in range(n+1):
for j in range(min(i,k)+1):
if (j == 0 or j == i):
memo[i][j] = 1
else:
memo[i][j] = memo[i-1][j-1] + memo[i-1][j]
#end if
#end for
#end for
return memo[n][k]
def print_array(memo):
for i in range(len(memo)):
print('t'.join([str(x) for x in memo[i]]))
#main
n = 5
k = 2
print("top down DP")
memo = [[-1 for i in range(6)] for j in range(6)]
nCk = binomial_coeffs1(n, k)
print_array(memo)
print("C(n={}, k={}) = {}".format(n,k,nCk))
print("bottom up DP")
memo = [[-1 for i in range(6)] for j in range(6)]
nCk = binomial_coeffs2(n, k)
print_array(memo)
print("C(n={}, k={}) = {}".format(n,k,nCk))
Note: the size of the memo table is set to a small value (6) for display purposes, it should be increased if you are computing binomial coefficients for large n and k.
add a comment |
I recommend using dynamic programming (DP) for computing binomial coefficients. In contrast to direct computation, it avoids multiplication and division of large numbers. In addition to recursive solution, it stores previously solved overlapping sub-problems in a table for fast look-up. The code below shows bottom-up (tabular) DP and top-down (memoized) DP implementations for computing binomial coefficients.
def binomial_coeffs1(n, k):
#top down DP
if (k == 0 or k == n):
return 1
if (memo[n][k] != -1):
return memo[n][k]
memo[n][k] = binomial_coeffs1(n-1, k-1) + binomial_coeffs1(n-1, k)
return memo[n][k]
def binomial_coeffs2(n, k):
#bottom up DP
for i in range(n+1):
for j in range(min(i,k)+1):
if (j == 0 or j == i):
memo[i][j] = 1
else:
memo[i][j] = memo[i-1][j-1] + memo[i-1][j]
#end if
#end for
#end for
return memo[n][k]
def print_array(memo):
for i in range(len(memo)):
print('t'.join([str(x) for x in memo[i]]))
#main
n = 5
k = 2
print("top down DP")
memo = [[-1 for i in range(6)] for j in range(6)]
nCk = binomial_coeffs1(n, k)
print_array(memo)
print("C(n={}, k={}) = {}".format(n,k,nCk))
print("bottom up DP")
memo = [[-1 for i in range(6)] for j in range(6)]
nCk = binomial_coeffs2(n, k)
print_array(memo)
print("C(n={}, k={}) = {}".format(n,k,nCk))
Note: the size of the memo table is set to a small value (6) for display purposes, it should be increased if you are computing binomial coefficients for large n and k.
add a comment |
I recommend using dynamic programming (DP) for computing binomial coefficients. In contrast to direct computation, it avoids multiplication and division of large numbers. In addition to recursive solution, it stores previously solved overlapping sub-problems in a table for fast look-up. The code below shows bottom-up (tabular) DP and top-down (memoized) DP implementations for computing binomial coefficients.
def binomial_coeffs1(n, k):
#top down DP
if (k == 0 or k == n):
return 1
if (memo[n][k] != -1):
return memo[n][k]
memo[n][k] = binomial_coeffs1(n-1, k-1) + binomial_coeffs1(n-1, k)
return memo[n][k]
def binomial_coeffs2(n, k):
#bottom up DP
for i in range(n+1):
for j in range(min(i,k)+1):
if (j == 0 or j == i):
memo[i][j] = 1
else:
memo[i][j] = memo[i-1][j-1] + memo[i-1][j]
#end if
#end for
#end for
return memo[n][k]
def print_array(memo):
for i in range(len(memo)):
print('t'.join([str(x) for x in memo[i]]))
#main
n = 5
k = 2
print("top down DP")
memo = [[-1 for i in range(6)] for j in range(6)]
nCk = binomial_coeffs1(n, k)
print_array(memo)
print("C(n={}, k={}) = {}".format(n,k,nCk))
print("bottom up DP")
memo = [[-1 for i in range(6)] for j in range(6)]
nCk = binomial_coeffs2(n, k)
print_array(memo)
print("C(n={}, k={}) = {}".format(n,k,nCk))
Note: the size of the memo table is set to a small value (6) for display purposes, it should be increased if you are computing binomial coefficients for large n and k.
I recommend using dynamic programming (DP) for computing binomial coefficients. In contrast to direct computation, it avoids multiplication and division of large numbers. In addition to recursive solution, it stores previously solved overlapping sub-problems in a table for fast look-up. The code below shows bottom-up (tabular) DP and top-down (memoized) DP implementations for computing binomial coefficients.
def binomial_coeffs1(n, k):
#top down DP
if (k == 0 or k == n):
return 1
if (memo[n][k] != -1):
return memo[n][k]
memo[n][k] = binomial_coeffs1(n-1, k-1) + binomial_coeffs1(n-1, k)
return memo[n][k]
def binomial_coeffs2(n, k):
#bottom up DP
for i in range(n+1):
for j in range(min(i,k)+1):
if (j == 0 or j == i):
memo[i][j] = 1
else:
memo[i][j] = memo[i-1][j-1] + memo[i-1][j]
#end if
#end for
#end for
return memo[n][k]
def print_array(memo):
for i in range(len(memo)):
print('t'.join([str(x) for x in memo[i]]))
#main
n = 5
k = 2
print("top down DP")
memo = [[-1 for i in range(6)] for j in range(6)]
nCk = binomial_coeffs1(n, k)
print_array(memo)
print("C(n={}, k={}) = {}".format(n,k,nCk))
print("bottom up DP")
memo = [[-1 for i in range(6)] for j in range(6)]
nCk = binomial_coeffs2(n, k)
print_array(memo)
print("C(n={}, k={}) = {}".format(n,k,nCk))
Note: the size of the memo table is set to a small value (6) for display purposes, it should be increased if you are computing binomial coefficients for large n and k.
answered Aug 1 '18 at 18:30
Vadim SmolyakovVadim Smolyakov
651417
651417
add a comment |
add a comment |
It's a good idea to apply a recursive definition, as in Vadim Smolyakov's answer, combined with a DP (dynamic programming), but for the latter you may apply the lru_cache decorator from module functools:
import functools
@functools.lru_cache(maxsize = None)
def binom(n,k):
if k == 0: return 1
if n == k: return 1
return binom(n-1,k-1)+binom(n-1,k)
add a comment |
It's a good idea to apply a recursive definition, as in Vadim Smolyakov's answer, combined with a DP (dynamic programming), but for the latter you may apply the lru_cache decorator from module functools:
import functools
@functools.lru_cache(maxsize = None)
def binom(n,k):
if k == 0: return 1
if n == k: return 1
return binom(n-1,k-1)+binom(n-1,k)
add a comment |
It's a good idea to apply a recursive definition, as in Vadim Smolyakov's answer, combined with a DP (dynamic programming), but for the latter you may apply the lru_cache decorator from module functools:
import functools
@functools.lru_cache(maxsize = None)
def binom(n,k):
if k == 0: return 1
if n == k: return 1
return binom(n-1,k-1)+binom(n-1,k)
It's a good idea to apply a recursive definition, as in Vadim Smolyakov's answer, combined with a DP (dynamic programming), but for the latter you may apply the lru_cache decorator from module functools:
import functools
@functools.lru_cache(maxsize = None)
def binom(n,k):
if k == 0: return 1
if n == k: return 1
return binom(n-1,k-1)+binom(n-1,k)
answered Jan 17 at 14:18
Jos VranckenJos Vrancken
1
1
add a comment |
add a comment |
The simplest way is using the Multiplicative formula. It works for (n,n) and (n,0) as expected.
def coefficient(n,k):
c = 1.0
for i in range(1, k+1):
c *= float((n+1-i))/float(i)
return c
Multiplicative formula
New contributor
add a comment |
The simplest way is using the Multiplicative formula. It works for (n,n) and (n,0) as expected.
def coefficient(n,k):
c = 1.0
for i in range(1, k+1):
c *= float((n+1-i))/float(i)
return c
Multiplicative formula
New contributor
add a comment |
The simplest way is using the Multiplicative formula. It works for (n,n) and (n,0) as expected.
def coefficient(n,k):
c = 1.0
for i in range(1, k+1):
c *= float((n+1-i))/float(i)
return c
Multiplicative formula
New contributor
The simplest way is using the Multiplicative formula. It works for (n,n) and (n,0) as expected.
def coefficient(n,k):
c = 1.0
for i in range(1, k+1):
c *= float((n+1-i))/float(i)
return c
Multiplicative formula
New contributor
New contributor
answered yesterday
assafshaassafsha
1
1
New contributor
New contributor
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f26560726%2fpython-binomial-coefficient%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
What do you need help with? The formula you're using for binomial coefficients doesn't look quite right, is that it?
– Joni
Oct 25 '14 at 8:53
why you are using
while
? you can merely useif
!!– Kasrâmvd
Oct 25 '14 at 8:55
when I input a number greater than x it comes up with an error or if x and y are equal to each other
– user3396351
Oct 25 '14 at 8:56
Enter a value for x: 1 Enter a value for y: 1 1 Traceback (most recent call last): File "D:CE151 Computer Programmingass1.py", line 122, in <module> elif len(line)==1 and "1"<=line<="8": exlist[int(line)]() File "D:CE151 Computer Programmingass1.py", line 83, in ex4 div = (a//(b*(x-y))) ZeroDivisionError: integer division or modulo by zero
– user3396351
Oct 25 '14 at 8:57
can you say what you want to do actually ?
– Kasrâmvd
Oct 25 '14 at 8:57