دقة COS (ATAN2 (y ، x)) مقابل استخدام المعقدة ، c ++
-
24-09-2019 - |
سؤال
أنا أكتب بعض التحولات الإحداثي (وبشكل أكثر تحديداً تحويل Joukoswky ، ويكيبيديا جوكوفسكي تحويل) ، وأنا مهتم بالأداء ، ولكن بالطبع الدقة. أحاول القيام بتحولات الإحداثيات بطريقتين:
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 هي هياكل بسيطة مع double x و y كأعضاء.
2) استخدام المجمع:
Z = 0.5 * (chi + (1.0 / chi));
حيث Z و Chi معقدة. هناك جزء مثير للاهتمام هو أن الحالة 1) أسرع (حوالي 20 ٪) ، لكن الدقة سيئة ، مما يعطي خطأ في الرقم العشري الثالث بعد الفاصلة بعد التحويل العكسي ، بينما يعيد المجمع الرقم الدقيق. إذن ، المشكلة على COS (ATAN2) ، الخطيئة (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);
أيضا تصحيح الخطأ على ZY
المحلول
أعتقد أنه في 1) يجب أن يكون
Z.y = 0.5*(si*sq - si/sq);
إذا كنت تريد أداء جيد حقًا ، فقد ترغب في العودة إلى المبادئ الأولى ومراقبة ذلك
1/(a+ib) = (a-ib)/(a*a+b*b)
لا sqrt()
, atan2()
أو cos()
أو sin()
.
نصائح أخرى
منح r = sqrt(x*x+y*y)
:
cos(atan2(y,x)) == x/r
sin(atan2(y,x)) == y/r
يجب أن يكون حسابه بهذه الطريقة أكثر دقة وأسرع.
عندما تقوم بتوصيل هذه القيم في الصيغ لـ ZX و ZY ، سيتم إلغاء الجذر التربيعي أيضًا ، لذلك ستترك مع عمليات حسابية أساسية فقط.