我需要返回大数组中每个元素的sin和cos值。我正在做的那一刻:
a,b=np.sin(x),np.cos(x)
其中x是一些大型数组。我需要保留每个结果的符号信息,所以:
a=np.sin(x)
b=(1-a**2)**0.5
不是一种选择。有没有更快的方法同时返回罪和cos?
答案 0 :(得分:2)
你可以使用复数和 e i·φ = cos(φ)+ i·sin(φ)这一事实。
import numpy as np
from cmath import rect
nprect = np.vectorize(rect)
x = np.arange(2 * np.pi, step=0.01)
c = nprect(1, x)
a, b = c.imag, c.real
我在这里使用来自https://stackoverflow.com/a/27788291/674064的技巧来制作cmath.rect()
的版本,它将接受并返回NumPy数组。
但这并没有在我的机器上获得任何加速:
c = nprect(1, x)
a, b = c.imag, c.real
需要大约三倍的时间(160μs)
a, b = np.sin(x), np.cos(x)
接受了我的测量(50.4μs)。
答案 1 :(得分:2)
我将建议的解决方案与perfplot进行了比较,发现没有必要明确地调用sin
和cos
。
用于重现情节的代码:
import perfplot
import numpy as np
def sin_cos(x):
return np.sin(x), np.cos(x)
def exp_ix(x):
eix = np.exp(1j * x)
return eix.imag, eix.real
def cos_from_sin(x):
sin = np.sin(x)
abs_cos = np.sqrt(1 - sin ** 2)
sgn_cos = np.sign(((x - np.pi / 2) % (2 * np.pi)) - np.pi)
cos = abs_cos * sgn_cos
return sin, cos
perfplot.save(
"out.png",
setup=lambda n: np.linspace(0.0, 2 * np.pi, n),
kernels=[sin_cos, exp_ix, cos_from_sin],
n_range=[2 ** k for k in range(20)],
xlabel="n",
)
答案 2 :(得分:0)
你可以利用tan(x)包含sin(x)和cos(x)函数的事实。所以你可以使用tan(x)并使用公共变换函数检索cos(x)和sin(x)。
答案 3 :(得分:0)
def cosfromsin(x,sinx):
cosx=absolute((1-sinx**2)**0.5)
signx=sign(((x-pi/2)%(2*pi))-pi)
return cosx*signx
a=sin(x)
b=cosfromsin(x,a)
我刚刚计时,它比使用sin和cos快25%。
答案 4 :(得分:0)
通过复数的纯粹numpy版本, e iφ =cosφ+isinφ, 灵感来自das-g的答案。
x = np.arange(2 * np.pi, step=0.01)
eix = np.exp(1j*x)
cosx, sinx = eix.real, eix.imag
这比nprect
快,但仍然比sin
和cos
调用慢:
In [6]: timeit c = nprect(1, x); cosx, sinx = cos(x), sin(x)
1000 loops, best of 3: 242 us per loop
In [7]: timeit eix = np.exp(1j*x); cosx, sinx = eix.real, eix.imag
10000 loops, best of 3: 49.1 us per loop
In [8]: timeit cosx, sinx = cos(x), sin(x)
10000 loops, best of 3: 32.7 us per loop