2015-09-04 14 views
12

Мне нужно вернуть значения sin и cos для каждого элемента в большом массиве. В настоящий момент я делаю:Есть ли быстрый способ вернуть Sin и Cos такого же значения в Python?

a,b=np.sin(x),np.cos(x) 

где x - некоторый большой массив. Мне нужно сохранить информацию о знаке для каждого результата, поэтому:

a=np.sin(x) 
b=(1-a**2)**0.5 

не является вариантом. Есть ли более быстрый способ сразу вернуть как sin, так и cos?

+1

* грех * 90- * х * = * соз х * – tripleee

+0

ли я правильно понимаю ваш вопрос? В основном вы спрашиваете: если я уже вычислил 'np.sin (x)', могу ли я использовать эту информацию, чтобы получить 'cos (x)' быстрее, чем вычисление 'np.cos (x)'? – cel

+6

OP наклонно ссылается на то, что некоторые математические библиотеки (и математическое оборудование) имеют функцию [sincos] (http://linux.die.net/man/3/sincos), которая одновременно возвращает и sin & cos для данный аргумент. Поэтому неразумно задаваться вопросом, может ли numpy это сделать, ИМО. –

ответ

0

Вы можете воспользоваться тем, что tan (x) содержит функции sin (x) и cos (x). Таким образом, вы можете использовать tan (x) и извлечь cos (x) ans sin (x) с помощью общей функции преобразования.

+1

Как вы получаете правильную информацию о знаке? Вы просто проверяете, в каком квадранте x? –

+0

Очень хороший момент, я бы забыл, что это также теряет информацию о знаке ... если мне нужно получить квадрант угла, я могу просто использовать альтернативный метод в своем оригинальном посте. Проблема остается; как быстро определить квадрант всех элементов в массиве? – rylirk

+0

Извлечение знака действительно потеряло преимущество этого метода, я полагаю, – vathek

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) 

Я только что приурочил это, и это примерно на 25% быстрее, чем использование sin и cos.

+0

Что вы на самом деле хотите? И насколько велик массив 'x', когда вы его приурочили? Когда я прекомпретирую «sinx» и сравниваю время «cos (x)» и «cosfromsin (x, sinx)», «cosfromsinx» работает медленнее. –

+0

Вот что я сделал. Объект I, переданный в cos и cosfrom sin, представлял собой двумерную матрицу с размерами примерно 2000 * 1000 – rylirk

+0

. Этот 'cosfromsin (x)', с учетом 'sin (x)', медленнее ~ 4x, чем 'cos (x) 'здесь тоже для таких размеров массива (и еще хуже для маленьких). Примечание: 'absolute' можно отбросить. 'signcos = (np.int _ ((x - pi_2) // pi) & 1) * 2 - 1' немного ускоряется, но все равно не будет бить. – kxr

2

Вы можете использовать сложные номера и тот факт, что e i & middot; φ = cos (φ) + i & middot; 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 μ сек), что

a, b = np.sin(x), np.cos(x) 

принял в моем измерении (50,4 μ с).

+1

Да, я пробовал аналогичный метод, но, к сожалению, он намного медленнее – rylirk

0

Чистая версия NumPy с помощью комплексных чисел, е я φ = соз φ + грешит φ, вдохновленного ответ от 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