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)
Ce programme coeeficient binomial fonctionne, mais lorsque j’en saisis deux du même nombre qui est supposé égal à 1 ou lorsque y est supérieur à x, il est supposé égal à 0. le programme doit être légèrement modifié si quelqu'un peut m'aider
Votre programme continuera avec la deuxième instruction if
dans le cas de y == x
, provoquant une ZeroDivisionError
. Vous devez faire les déclarations mutuellement exclusives; Pour ce faire, utilisez Elif
("else if") au lieu de 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)
Cette question est ancienne, mais comme elle figure en bonne place dans les résultats de recherche, je soulignerai que scipy
a deux fonctions pour calculer les coefficients binomiaux:
scipy.special.binom()
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
Notez que scipy.special.comb(exact=True)
utilise des entiers Python et qu'il peut donc gérer des résultats arbitrairement volumineux!
En termes de vitesse, les trois versions donnent des résultats quelque peu différents:
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)
(et pour n = 300
, les coefficients binomiaux sont trop importants pour être représentés correctement avec les nombres float64
, comme indiqué ci-dessus).
Voici une version qui utilise réellement la formule correcte . :)
#! /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 __== '__main__':
#Pascal(8)
main()
...
Voici une autre version de binomial()
que j'ai écrite il y a plusieurs années et qui n'utilise pas math.factorial()
, qui n'existait pas dans les anciennes versions de Python. Cependant, il retourne 1 si r n'est pas dans la plage (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
Donc, cette question revient en premier si vous recherchez "Implémentez des coefficients binomiaux en Python". Seule this answer dans sa deuxième partie contient une implémentation efficace reposant sur la formule multiplicative . Cette formule effectue le nombre minimum de multiplications. La fonction ci-dessous ne dépend d'aucun élément intégré ou importé:
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
Enfin, si vous avez besoin de valeurs encore plus grandes et que l’échange de précision ne vous dérange pas, l’approximation de Stirling est probablement la solution.
Pour Python 3, scipy a la fonction scipy.special.comb, qui peut produire des résultats en virgule flottante ainsi que des entiers exacts.
import scipy.special
res = scipy.special.comb(x, y, exact=True)
Voir la documentation de scipy.special.comb .
Pour Python 2, la fonction est située dans scipy.misc et fonctionne de la même manière:
import scipy.misc
res = scipy.misc.comb(x, y, exact=True)
Voici une fonction qui calcule de manière récursive les coefficients binomiaux à l'aide d'expressions conditionnelles
def binomial(n,k):
return 1 if k==0 else (0 if n==0 else binomial(n-1, k) + binomial(n-1, k-1))
Qu'en est-il de celui-ci? :) Il utilise la formule correcte, évite math.factorial
et nécessite moins d'opérations de multiplication:
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)
De plus, pour éviter les arithmétiques de grand entier, vous pouvez utiliser des nombres en virgule flottante, convertir product(a[i])/product(b[i])
en product(a[i]/b[i])
et réécrire le programme ci-dessus de la manière suivante:
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)))
Je recommande d'utiliser la programmation dynamique (DP) pour calculer les coefficients binomiaux. Contrairement au calcul direct, il évite la multiplication et la division de grands nombres. En plus de la solution récursive, il stocke dans une table les sous-problèmes qui se chevauchent et se chevauchent pour une recherche rapide. Le code ci-dessous montre les implémentations DP ascendantes (tabulaires) et DP descendantes (mémoisées) pour le calcul des coefficients binomiaux.
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))
Remarque: la taille de la table des notes est définie sur une petite valeur (6) à des fins d'affichage. Elle doit être augmentée si vous calculez des coefficients binomiaux pour les grands n et k.
C'est une bonne idée d'appliquer une définition récursive, comme dans la réponse de Vadim Smolyakov, associée à un DP (programmation dynamique), mais pour ce dernier, vous pouvez appliquer le décorateur lru_cache du 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)