如果您提供(整数)幂作为输入,那么创建相应的 10 次幂的最快方法是什么?我可以提出以下四种替代方案,最快的方法似乎是使用 f 字符串:
from functools import partial
from time import time
import numpy as np
def fstring(power):
return float(f'1e{power}')
def asterisk(power):
return 10**power
methods = {
'fstring': fstring,
'asterisk': asterisk,
'pow': partial(pow, 10),
'np.pow': partial(np.power, 10, dtype=float)
}
# "dtype=float" is necessary because otherwise it will raise:
# ValueError: Integers to negative integer powers are not allowed.
# see https://stackoverflow.com/a/43287598/5472354
powers = [int(i) for i in np.arange(-10000, 10000)]
for name, method in methods.items():
start = time()
for i in powers:
method(i)
print(f'{name}: {time() - start}')
Run Code Online (Sandbox Code Playgroud)
结果:
fstring: 0.008975982666015625
asterisk: 0.5190775394439697
pow: 0.4863283634185791
np.pow: 0.046906232833862305
Run Code Online (Sandbox Code Playgroud)
我猜 f 字符串方法是最快的,因为实际上没有计算任何内容,尽管它只适用于 10 的整数幂,而其他方法是更复杂的运算,也适用于任何实数作为基数和幂。那么 F 弦实际上是解决这个问题的最佳方法吗?
您在这里将苹果与橙子进行比较。10 ** n计算整数(当n为非负数时),而float(f'1e{n}')计算浮点数。这些不会花费相同的时间,但它们解决不同的问题,所以哪个更快并不重要。
但比这更糟糕的是,因为存在调用函数的开销,该开销包含在所有替代方案的计时中,但只有其中一些实际上涉及调用函数。如果您编写10 ** n,那么您就不会调用函数,但如果您使用partial(pow, 10),则必须将其作为函数调用才能获得结果。所以你实际上并没有公平地比较速度10 ** n。
不要滚动自己的计时代码,而是使用timeit专为正确执行此操作而设计的库。结果以秒为单位,表示 1,000,000 次重复(默认情况下),或者等效地,它们是一次重复的平均时间(以微秒为单位)。
下面是计算 10 的整数幂的比较:
>>> from timeit import timeit
>>> timeit('10 ** n', setup='n = 500')
1.09881673199925
>>> timeit('pow(10, n)', setup='n = 500')
1.1821871869997267
>>> timeit('f(n)', setup='n = 500; from functools import partial; f = partial(pow, 10)')
1.1401332350014854
Run Code Online (Sandbox Code Playgroud)
下面是计算 10 的浮点幂的比较:请注意,计算10.0 ** 500or1e500是没有意义的,因为结果只是一个OverflowErroror inf。
>>> timeit('10.0 ** n', setup='n = 200')
0.12391662099980749
>>> timeit('pow(10.0, n)', setup='n = 200')
0.17336435099969094
>>> timeit('f(n)', setup='n = 200; from functools import partial; f = partial(pow, 10.0)')
0.18887039500077663
>>> timeit('float(f"1e{n}")', setup='n = 200')
0.44305286100097874
>>> timeit('np.power(10.0, n, dtype=float)', setup='n = 200; import numpy as np')
1.491982370000187
>>> timeit('f(n)', setup='n = 200; from functools import partial; import numpy as np; f = partial(np.power, 10.0, dtype=float)')
1.6273324920002779
Run Code Online (Sandbox Code Playgroud)
因此,在这两种情况下,这些选项中最快的选项是显而易见的:10 ** n对于整数和10.0 ** n浮点数。