Precisão de cos (atan2 (y, x)) versus usar complexo , c ++
-
24-09-2019 - |
Pergunta
Estou escrevendo algumas transformações de coordenadas (mais especificamente a transformação Joukoswky, Wikipedia Joukowsky Transform), e estou interessado em desempenho, mas é claro que precisão. Estou tentando fazer as transformações de coordenadas de duas maneiras:
1) Calcular as peças reais e complexas em separado, usando dupla precisão, como abaixo:
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;
onde chi e z são estruturas simples com x e y como membros.
2) Usando o complexo:
Z = 0.5 * (chi + (1.0 / chi));
Onde z e chi são complexos. A parte interessante é que, de fato, o caso 1) é mais rápido (cerca de 20%), mas a precisão é ruim, dando erro no terceiro número decimal após a vírgula após a transformação inversa, enquanto o complexo retribui o número exato. Então, o problema está no COS (ATAN2), SIN (ATAN2)? Mas se for, como o complexo lida com isso?
EDIT: Acabei de descobrir que essa não era exatamente a pergunta que eu tinha em mente. Eu tenho que fazer a transformação geral, como
Z = 1/2*(chi^n + (1/chi)^n) e, até agora, o código acima foi a maneira como eu imaginei fazê -lo. Mais precisamente,
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);
Também corrigindo o bug em zy
Solução
Eu acho que em 1) deve ser
Z.y = 0.5*(si*sq - si/sq);
Se você quer um desempenho realmente bom, pode voltar aos primeiros princípios e observar isso
1/(a+ib) = (a-ib)/(a*a+b*b)
Não sqrt()
, atan2()
ou cos()
ou sin()
.
Outras dicas
Dado r = sqrt(x*x+y*y)
:
cos(atan2(y,x)) == x/r
sin(atan2(y,x)) == y/r
Calcular dessa maneira deve ser mais preciso e mais rápido.
Quando você conecta esses valores às fórmulas para ZX e ZY, a raiz quadrada também será cancelada, para que você fique apenas com operações aritméticas básicas.