在物理学的某些领域中,相位因子,如(-1)^n,其中n是通过求和或减去其他整数而形成的整数,经常出现。总体而言,是否有以下方面的绩效改进:
sgn = lambda k: -1 if k % 2 else 1
太简单了
sgn = (-1)**k
如果是这样的话,那么将前者矢量化的最佳方法是什么?
编辑:E先生提供了一个在整数范围内有界的
k
的快速解决方案,但我有点担心我的k
可能会超出这个范围。最初我想:In [1]: sg = np.array([1,-1])
In [2]: k = np.array([201, 0, 2, -37])
In [3]: sg[k % 2]
Out[4]: array([-1, 1, 1, -1])
但是,与功率法相比,模数运算似乎减慢了速度:
ph1 = lambda k: (-1)**k
sgn = np.array([1,-1])
ph2 = lambda k: sgn[k % 2]
x = np.random.randint(-200, 200, 100)
%timeit ph1(x)
1000000 loops, best of 3: 264 ns per loop
%timeit ph2(x)
1000000 loops, best of 3: 284 ns per loop
最佳答案
Mr E has answered how to vectorise it with numpy,但对于哪个时间段更有效,下面的代码对timeit
的各种值使用k
,并使用matplotlib绘制结果。
结果表明,使用-1 if k % 2 else 1
始终比使用(-1)**k
快。
import matplotlib.pyplot as plt
from timeit import Timer
def f1(k): return -1 if k % 2 else 1
def f2(k): return (-1)**k
result1 = []
result2 = []
x = range(0,1000, 100)
for n in x:
print(n)
timer1 = Timer('f1({})'.format(n), setup='from __main__ import f1')
timer2 = Timer('f2({})'.format(n), setup='from __main__ import f2')
result1.append(timer1.timeit(100000))
result2.append(timer2.timeit(100000))
plt.plot(x, result1, label='-1 if k % 2 else 1')
plt.plot(x, result2, label='(-1)**k')
plt.xlabel('k')
plt.ylabel('Time')
plt.legend(loc='best')
plt.show()