Est-il concluant que maintenant l' scipy.misc.comb
est en effet plus rapide que le ad-hoc mise en œuvre?
Selon une vieille réponse, les Statistiques: les combinaisons en Python, ce homebrew fonction est plus rapide que l' scipy.misc.comb
lors du calcul de combinaisons nCr
:
def choose(n, k):
"""
A fast way to calculate binomial coefficients by Andrew Dalke (contrib).
"""
if 0 <= k <= n:
ntok = 1
ktok = 1
for t in xrange(1, min(k, n - k) + 1):
ntok *= n
ktok *= t
n -= 1
return ntok // ktok
else:
return 0
Mais après l'exécution de certains tests sur ma machine, cela ne semble pas être le cas, à l'aide de ce script:
from scipy.misc import comb
import random, time
def choose(n, k):
"""
A fast way to calculate binomial coefficients by Andrew Dalke (contrib).
"""
if 0 <= k <= n:
ntok = 1
ktok = 1
for t in xrange(1, min(k, n - k) + 1):
ntok *= n
ktok *= t
n -= 1
return ntok // ktok
else:
return 0
def timing(f):
def wrap(*args):
time1 = time.time()
ret = f(*args)
time2 = time.time()
print '%s function took %0.3f ms' % (f.__name__, (time2-time1)*1000.0)
return ret
return wrap
@timing
def test_func(combination_func, nk):
for n,k in nk:
combination_func(n, k)
nk = []
for _ in range(1000):
n = int(random.random() * 10000)
k = random.randint(0,n)
nk.append((n,k))
test_func(comb, nk)
test_func(choose, nk)
J'obtiens le résultat suivant:
$ python test.py
/usr/lib/python2.7/dist-packages/scipy/misc/common.py:295: RuntimeWarning: overflow encountered in exp
vals = exp(lgam(N+1) - lgam(N-k+1) - lgam(k+1))
999
test_func function took 32.869 ms
999
test_func function took 1859.125 ms
$ python test.py
/usr/lib/python2.7/dist-packages/scipy/misc/common.py:295: RuntimeWarning: overflow encountered in exp
vals = exp(lgam(N+1) - lgam(N-k+1) - lgam(k+1))
999
test_func function took 32.265 ms
999
test_func function took 1878.550 ms
N'a le temps de test de profil montrent que le nouveau scipy.misc.comb
est plus rapide que le ad-hoc choose()
fonction? Est-il une erreur de mon script de test qui rend le moment inexactes?
Pourquoi est-ce que l' scipy.misc.comb
est plus rapide maintenant? C'est à cause de certains cython
/ c
emballage astuces?
ÉDITÉ
Après @WarrenWeckesser commentaire:
À l'aide de la valeur par défaut de point flottant de rapprochement lors de l'utilisation d' scipy.misc.comb()
, le calcul des pauses à cause de la virgule flottante de débordement.
(voir http://docs.scipy.org/doc/scipy-0.16.0/reference/generated/scipy.misc.comb.html pour la documentation)
Lorsqu'il est testé avec exact=True
qui calcule avec des entiers longs au lieu de la virgule flottante à l'aide de la fonction ci-dessous, c'est beaucoup plus lent lors du calcul de 1000 combinaisons:
@timing
def test_func(combination_func, nk):
for i, (n,k) in enumerate(nk):
combination_func(n, k, exact=True)
[out]:
$ python test.py
test_func function took 3312.211 ms
test_func function took 1764.523 ms
$ python test.py
test_func function took 3320.198 ms
test_func function took 1782.280 ms