Precisione di cos (atan2 (y, x)) rispetto all'utilizzo complesso , C ++
-
24-09-2019 - |
Domanda
Sto scrivendo alcune trasformazioni di coordinate (più precisamente il Joukoswky Transform, Wikipedia Joukowsky Transform ), e mi sono interessato in termini di prestazioni, ma ovviamente di precisione. Sto cercando di fare la trasformazioni di coordinate in due modi:
1) Calcolare le parti reali e complessi separati, utilizzando doppia precisione, come di seguito:
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;
dove chi e Z sono strutture semplici con doppio xey come membri.
2) Uso di complesso:
Z = 0.5 * (chi + (1.0 / chi));
Dove Z e chi sono complesse. Ci parte interessante è che davvero il caso 1) è più veloce (circa 20%), ma la precisione è male, dando errore nel terzo numero decimale dopo la virgola dopo la trasformata inversa, mentre il complesso dà indietro il numero esatto. Quindi, il problema è sulle cos (atan2), sin (atan2)? Ma se lo è, come le maniglie complessi che?
EDIT: appena capito che questo non era esattamente la domanda che avevo in mente. Devo fare la trasformazione generale, come
Z = 1/2 * (chi ^ n + (1 / CHI) ^ n), e finora il codice di cui sopra è stato il modo in cui ho pensato di farlo. Più 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);
Anche la correzione bug su Z.y.
Soluzione
Credo che in 1) dovrebbe essere
Z.y = 0.5*(si*sq - si/sq);
Se si vuole veramente buone prestazioni si consiglia di tornare a principi primi e osservare che
1/(a+ib) = (a-ib)/(a*a+b*b)
No sqrt()
, atan2()
o cos()
o sin()
.
Altri suggerimenti
r = sqrt(x*x+y*y)
Data:
cos(atan2(y,x)) == x/r
sin(atan2(y,x)) == y/r
Il calcolo in questo modo dovrebbe essere più accurato e veloce.
Quando si collega questi valori nelle formule per Z.x e Z.y, la radice quadrata annullerà fuori pure, così ti verrà lasciato con le operazioni aritmetiche di base solo.