为什么math.factorial比scipy.special.factorial快这么多
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)
发布于 2018-12-21 19:55:37
这是一个常见的错误,类似于期望像np.exp()这样的东西比math模块工作得更快。这不是这些函数的目的。科学堆栈(NumPy、Pandas、SciPy和其他)关注的是跨数组的矢量化方法,而不是单个值。
from math import factorial
factorial([20, 20, 20])这将为TypeError: an integer is required (got type list)提供
但是:
from scipy.special import factorial
factorial([20, 20, 20])将计算整个列表的阶乘,给出:
array([2.43290201e+18, 2.43290201e+18, 2.43290201e+18])如果您将math.factorial计算放到for循环中以覆盖列表中的多个项目,那么与矢量化方法相比,它很快就会落后于时间(如果您首先提供的是NumPy数组而不是列表,这将会更快)
发布于 2018-12-21 20:05:59
除了已经提到的关于scipy针对矢量化输入的事实-你在这里使用了一个非常小的测试用例-如果你扩大它,它就不会那么清楚了:
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}")输出:
# 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 -因此不认真计算它,计时是不正确的
发布于 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的小值的精确计算慢。
https://stackoverflow.com/questions/53884289
复制相似问题