Точность cos (atan2 (y, x)) по сравнению с использованием комплекса <double>, C ++ - PullRequest
0 голосов
/ 06 апреля 2010

Я пишу некоторые преобразования координат (более конкретно, преобразование Joukoswky, Wikipedia Joukowsky Transform ), и меня интересует производительность, но, конечно, точность. Я пытаюсь сделать преобразования координат двумя способами:

1) Вычисление реальных и сложных деталей по отдельности с использованием двойной точности, как показано ниже:

double r2 = chi.x*chi.x + chi.y*chi.y;

//double sq = pow(r2,-0.5*n) + pow(r2,0.5*n); //slow!!!
double sq = sqrt(r2); //way faster!
double co = cos(atan2(chi.y,chi.x));
double si = sin(atan2(chi.y,chi.x));

Z.x = 0.5*(co*sq + co/sq);
Z.y = 0.5*si*sq;

где chi и Z - простые структуры с двойными x и y в качестве членов.

2) Использование комплекса:

Z = 0.5 * (chi + (1.0 / chi));

Где Z и Чи сложны. Интересная часть состоит в том, что действительно случай 1) быстрее (около 20%), но точность плохая, что дает ошибку в третьем десятичном числе после запятой после обратного преобразования, в то время как комплекс возвращает точное число. Итак, проблема в cos (atan2), sin (atan2)? Но если это так, как комплекс справляется с этим?

РЕДАКТИРОВАТЬ: Просто понял, что это не совсем тот вопрос, который я имел в виду. Я должен сделать общее преобразование, как

Z = 1/2 * (chi ^ n + (1 / chi) ^ n), и до сих пор приведенный выше код был способом, которым я рассчитывал сделать это. Точнее,

    double sq = pow(sqrt(r2),n); //way faster!
double co = cos(n*atan2(chi.y,chi.x));
double si = sin(n*atan2(chi.y,chi.x));

Z.x = 0.5*(co*sq + co/sq);
Z.y = 0.5*(si*sq - sq/si);

Также исправление ошибки на Z.y.

Ответы [ 2 ]

5 голосов
/ 06 апреля 2010

Дано r = sqrt(x*x+y*y):

cos(atan2(y,x)) == x/r
sin(atan2(y,x)) == y/r

Такой способ расчета должен быть более точным и быстрым.

Когда вы вставляете эти значения в формулы для Z.x и Z.y, квадратный корень также отменяется, поэтому у вас останутся только основные арифметические операции.

3 голосов
/ 06 апреля 2010

Я думаю, что в 1) это должно быть

Z.y = 0.5*(si*sq - si/sq);

Если вы хотите действительно хорошую производительность, вы можете вернуться к первым принципам и соблюдать это

1/(a+ib) = (a-ib)/(a*a+b*b)

Нет sqrt(), atan2() или cos() или sin().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...