Python二项式系数

时间:2014-10-25 08:50:26

标签: 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)  

这个二项式系数程序有效,但是当我输入两个相同的数字时,它应该等于1,或者当y大于x时,它应该等于0。

12 个答案:

答案 0 :(得分:20)

这是一个实际使用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()

...

这是我几年前写的binomial()的替代版本,它不使用math.factorial(),而旧版本的Python中并不存在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 。但是,如果r不在范围(0,n + 1)内,则返回1.

{{1}}

答案 1 :(得分:3)

因此,如果您在Python"中搜索"实现二项式系数,那么首先会出现这个问题。第二部分中只有this answer包含一个依赖multiplicative formula的有效实现。该公式执行最小的乘法次数。以下功能不依赖于任何内置插件或导入:

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

最后,如果您需要更大的值并且不介意交易一些准确性,Stirling's approximation可能是要走的路。

答案 2 :(得分:2)

对于Python 3,scipy具有scipy.special.comb函数,它可以产生浮点数以及精确的整数结果

import scipy.special

res = scipy.special.comb(x, y, exact=True)

请参阅scipy.special.comb的文档。

对于Python 2,该函数位于scipy.misc中,它的工作方式相同:

import scipy.misc

res = scipy.misc.comb(x, y, exact=True)

答案 3 :(得分:1)

对于if,您的程序将继续使用第二个y == x语句,从而导致ZeroDivisionError。你需要使这些陈述互相排斥;这样做的方法是使用elif(“else if”)而不是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)  

答案 4 :(得分:1)

这个怎么样? :)它使用正确的公式,避免math.factorial并减少乘法运算:

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)

另外,为了避免大整数算术,你可以使用浮点数,转换 product(a[i])/product(b[i])product(a[i]/b[i])并将上述程序重写为:

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)))

答案 5 :(得分:1)

这是一个使用条件表达式

递归计算二项式系数的函数
def binomial(n,k):
    return 1 if k==0 else (0 if n==0 else binomial(n-1, k) + binomial(n-1, k-1))

答案 6 :(得分:1)

PM 2Ringalisianoi给出的缩短的乘法变体。适用于python 3,不需要任何软件包。

def comb(n, k):
  # Remove the next two lines if out-of-range check is not needed
  if k < 0 or k > n:
    return None
  x = 1
  for i in range(min(k, n - k)):
    x = x*(n - i)//(i + 1)
  return x

from functools import reduce
def comb(n, k):
  return (None if k < 0 or k > n else
    reduce(lambda x, i: x*(n - i)//(i + 1), range(min(k, n - k)), 1))

除法后立即进行除法以不累积高数字。

答案 7 :(得分:0)

我建议使用动态编程(DP)来计算二项式系数。与直接计算相反,它避免了大数的乘法和除法。除递归解决方案外,它还将以前解决的重叠子问题存储在表中,以便快速查找。下面的代码显示了用于计算二项式系数的自下而上(表格)DP和自上而下(内存化)DP实现。

class B: ViewController {

@IBOutlet weak var server: UITextField!
@IBOutlet weak var port: UITextField!
 let objA= A()
 @IBAction func save(_ sender: Any) {
        objA.updateServerAndport(s = server.text!, p : port.text!)
}
}

注意:出于显示目的,备忘录表的大小设置为较小的值(6),如果要计算较大的n和k的二项式系数,则应将其增加。

答案 8 :(得分:0)

最好采用递归定义,如Vadim Smolyakov的回答,并结合DP(动态编程),但是对于后者,您可以从模块functools应用lru_cache装饰器:

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)

答案 9 :(得分:0)

最简单的方法是使用乘法公式。按预期,它适用于(n,n)和(n,0)。

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

答案 10 :(得分:0)

请注意,从Python 3.8开始,标准库提供了math.comb函数来计算二项式系数:

  

math.comb(n,k)

这是从n个项目中选择k个项目而无需重复的方式的数量
n! / (k! (n - k)!)

import math
math.comb(10, 5)  # 252
math.comb(10, 10) # 1

答案 11 :(得分:0)

对于寻找二项式系数的 log (Theano称为binomln)的每个人,this answer都有:

from numpy import log
from scipy.special import betaln

def binomln(n, k):
    "Log of scipy.special.binom calculated entirely in the log domain"
    return -betaln(1 + n - k, 1 + k) - log(n + 1)

(而且,如果您的语言/图书馆缺少betaln但拥有gammaln(如Go),则不必担心,因为{{3} }。