首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >比较python factorial的性能(数学与scipy)

比较python factorial的性能(数学与scipy)
EN

Stack Overflow用户
提问于 2018-12-21 19:47:08
回答 4查看 631关注 0票数 1

为什么math.factorialscipy.special.factorial快这么多

代码语言:javascript
复制
import timeit

t = timeit.timeit("from math import factorial; factorial(20)"); print(t)
0.6399730000412092

t = timeit.timeit("from scipy.special import factorial; factorial(20)"); print(t)
5.339432950946502

t = timeit.timeit("from scipy.special import factorial; factorial(20, exact=True)"); print(t)
1.7984685270348564

我使用的是Python 3.7 (scipy版本是1.1.0)

EN

回答 4

Stack Overflow用户

发布于 2018-12-21 19:55:37

这是一个常见的错误,类似于期望像np.exp()这样的东西比math模块工作得更快。这不是这些函数的目的。科学堆栈(NumPyPandasSciPy和其他)关注的是跨数组的矢量化方法,而不是单个值。

代码语言:javascript
复制
from math import factorial

factorial([20, 20, 20])

这将为TypeError: an integer is required (got type list)提供

但是:

代码语言:javascript
复制
from scipy.special import factorial

factorial([20, 20, 20])

将计算整个列表的阶乘,给出:

代码语言:javascript
复制
array([2.43290201e+18, 2.43290201e+18, 2.43290201e+18])

如果您将math.factorial计算放到for循环中以覆盖列表中的多个项目,那么与矢量化方法相比,它很快就会落后于时间(如果您首先提供的是NumPy数组而不是列表,这将会更快)

票数 5
EN

Stack Overflow用户

发布于 2018-12-21 20:05:59

除了已经提到的关于scipy针对矢量化输入的事实-你在这里使用了一个非常小的测试用例-如果你扩大它,它就不会那么清楚了:

代码语言:javascript
复制
import timeit

for z in range(20,100000,10000):
    t1 = timeit.timeit(f"from math import factorial; factorial({z})",number=10)
    t2 = timeit.timeit(f"from scipy.special import factorial; factorial({z})",number=10)
    t3 = timeit.timeit(f"from scipy.special import factorial; factorial({z}, exact=True)",number=10)
    print(f"{z}  : {t1:<20}  {t2:<20}  {t3:<20}")

输出:

代码语言:javascript
复制
# facNr    factorial          scipy.special.factorial(*)   exact = True
   20  : 0.0003352240000822    0.18152283800009172     6.924199988134205e-05
10020  : 0.0368837539999731    0.00016821899953356478  0.03690350099986972 
20020  : 0.1258954189997894    0.00016980899999907706  0.12552139000035822 
30020  : 0.2532270950005113    0.00017434100027458044  0.2531732979996377  
40020  : 0.4068329990004713    0.00017545999980939087  0.406938215000082   
50020  : 0.6163399690003644    0.0001782059998731711   0.616294079999534   
60020  : 0.8626650409996728    0.00017887300055008382  0.8635997929995938  
70020  : 1.1321934719999263    0.00017422100063413382  1.130675204999534   
80020  : 1.369009857000492     0.00017408599978807615  1.369635687000482   
90020  : 1.7379734959995403    0.00017380499957653228  1.7343564000002516  

通过使用更大范围的输入,您会发现它并不总是快得多。

如果做计时,总是考虑少量和大量数据的边缘以及“正常数量”。

(*)对于z>170时返回inf -因此不认真计算它,计时是不正确的

票数 1
EN

Stack Overflow用户

发布于 2018-12-21 19:55:38

exact=True时,scipy函数实际上只是充当math.factorial的包装器(参见https://github.com/scipy/scipy/blob/v1.2.0/scipy/special/…)。所以我猜额外的时间只是参数检查逻辑和额外函数调用的开销。

如果为exact=False或未指定,则使用近似值,该近似值将比n的小值的精确计算慢。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53884289

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档