Python “scipy.misc.comb”比特殊的二项式计算快吗?

Python “scipy.misc.comb”比特殊的二项式计算快吗?,python,math,scipy,combinations,combinatorics,Python,Math,Scipy,Combinations,Combinatorics,现在的scipy.misc.comb确实比即席实现快,这是否具有决定性意义? 根据一个老的答案,当计算组合时,这个自制函数比scipy.misc.comb快nCr: def choose(n, k): """ A fast way to calculate binomial coefficients by Andrew Dalke (contrib). """ if 0 <= k <= n: ntok = 1 ktok

现在的
scipy.misc.comb
确实比即席实现快,这是否具有决定性意义?

根据一个老的答案,当计算组合时,这个自制函数比scipy.misc.comb快
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
时间分析测试是否显示新的
scipy.misc.comb
比特殊的
choose()
函数快?
我的测试脚本中是否有任何错误导致计时不准确

为什么
scipy.misc.comb
现在更快了?这是因为一些
cython
/
c
包装技巧?


编辑 @WarrenWeckesser评论之后:

使用
scipy.misc.comb()
时使用默认的浮点近似值,由于浮点溢出,计算中断

(有关文档,请参阅)

使用
exact=True
测试时,使用下面的函数使用长整数而不是浮点进行计算,计算1000个组合时速度要慢得多:

@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

参考的源代码,结果的更新例程为:

    val = 1
    for j in xrange(min(k, N-k)):
        val = (val*(N-j))//(j+1)
    return val
而您建议的更新例程是:

    ntok = 1
    ktok = 1
    for t in xrange(1, min(k, n - k) + 1):
        ntok *= n
        ktok *= t
        n -= 1
    return ntok // ktok

我猜测SciPy实现较慢的原因是,子例程在每次迭代中都涉及整数除法,而您的子例程在返回语句中只调用一次除法。

默认情况下,SciPy的
comb
计算浮点值,当参数足够大时,这将是一个近似值。您应该使用
comb
中的参数
exact=True
来比较计时。哇,使用
exact=True
后,它的速度非常慢。那么有没有理由不使用ad-hoc函数而不是
scipy.misc.comb
好问题!如果你觉得有动力,你可以添加任何与你的想法相关的评论
    val = 1
    for j in xrange(min(k, N-k)):
        val = (val*(N-j))//(j+1)
    return val
    ntok = 1
    ktok = 1
    for t in xrange(1, min(k, n - k) + 1):
        ntok *= n
        ktok *= t
        n -= 1
    return ntok // ktok