我从这个线程和这里链接的库中计时了 17 个不同的函数。
因为我觉得这里转储有点多,所以我把函数的代码放在了一个pastebin中。
我做的第一个测试是将帕斯卡三角形建立到第 100 行。我用 timeit 做了 100 次。下面的数字是构建一次三角形所需的平均时间(以秒为单位)。
gmpy2.gmpy2.comb 0.0012259269999998423
math.comb 0.007063110999999935
__main__.stdfactorial2 0.011469491
__main__.scipybinom 0.0120114319999999
__main__.stdfactorial 0.012105122
__main__.scipycombexact 0.012569045999999844
__main__.andrewdalke 0.01825201100000015
__main__.rabih 0.018472497000000202
__main__.kta 0.019374668000000383
__main__.wirawan 0.029312811000000067
scipy.special._basic.comb 0.03221609299999954
__main__.jfsmodifiedscipy 0.04332894699999997
__main__.rojas 0.04395155400000021
sympy.functions.combinatorial.factorials.binomial 0.3233529779999998
__main__.nasbanov 0.593365528
__main__.pantelis300 1.7780402499999999
您可能会注意到这里只有 16 个函数。那是因为该recursive()
函数甚至无法在合理的时间内完成一次,所以我不得不将它从 timeit 测试中排除。严重的是,它已经持续了几个小时。
我还计时了并非所有上述功能都支持的各种其他类型的输入。请记住,我只运行了每 10 次测试,因为 nCr 的计算量很大而且我很不耐烦
n 的小数值
__main__.scipybinom 0.011481370000000001
__main__.kta 0.01869513999999999
sympy.functions.combinatorial.factorials.binomial 6.33897291
r 的小数值
__main__.scipybinom 0.010960040000000504
scipy.special._basic.comb 0.03681254999999908
sympy.functions.combinatorial.factorials.binomial 3.2962564499999987
n 和 r 的小数值
__main__.scipybinom 0.008623409999998444
sympy.functions.combinatorial.factorials.binomial 3.690936439999999
n 的负值
gmpy2.gmpy2.comb 0.010770989999997482
__main__.kta 0.02187850000000253
__main__.rojas 0.05104292999999984
__main__.nasbanov 0.6153183200000001
sympy.functions.combinatorial.factorials.binomial 3.0460310799999943
n 的负小数值,r 的小数值
sympy.functions.combinatorial.factorials.binomial 3.7689941699999965
目前实现最大速度和多功能性的最佳解决方案是混合函数,可根据输入在不同算法之间进行选择
def hybrid(n: typing.Union[int, float], k: typing.Union[int, float]) -> typing.Union[int, float]:
# my own custom hybrid solution
def is_integer(n):
return isinstance(n, int) or n.is_integer()
if k < 0:
raise ValueError("k cannot be negative.")
elif n == 0:
return 0
elif k == 0 or k == n:
return 1
elif is_integer(n) and is_integer(k):
return int(gmpy2.comb(int(n), int(k)))
elif n > 0:
return scipy.special.binom(n, k)
else:
return float(sympy.binomial(n, k))
由于sympy.binomial()
速度如此之慢,真正理想的解决方案是组合scipy.special.binom()
对分数执行良好的代码和gmpy2.comb()
对整数执行良好的代码。scipy 的 func和gympy2 的 func都是用我不太熟悉的 C 语言编写的。