cos(atan2(y,x)) 与使用复数、C++ 的精度
我正在编写一些坐标变换(更具体地说是 Joukowsky 变换,Wikipedia Joukowsky 变换),并且我对性能感兴趣,当然还有精度。我尝试以两种方式进行坐标转换:
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和chi是复数。有趣的是,情况 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);
还纠正了 Zy 上的错误
I'm writing some coordinate transformations (more specifically the Joukoswky Transform, Wikipedia Joukowsky Transform), and I'm interested in performance, but of course precision. I'm trying to do the coordinate transformations in two ways:
1) Calculating the real and complex parts in separate, using double precision, as below:
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;
where chi and Z are simple structures with double x and y as members.
2) Using complex :
Z = 0.5 * (chi + (1.0 / chi));
Where Z and chi are complex . There interesting part is that indeed the case 1) is faster (about 20%), but the precision is bad, giving error in the third decimal number after the comma after the inverse transform, while the complex gives back the exact number.
So, the problem is on the cos(atan2), sin(atan2)? But if it is, how the complex handles that?
EDIT: Just figured out that this was not exactly the question that I had in mind. I have to do the general transformation, as
Z = 1/2*(chi^n + (1/chi)^n), and so far the code above was the way I've figured to do it. More precisely,
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);
Also correcting the bug on Z.y.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
给定 r = sqrt(x*x+y*y):
这样计算应该更准确、更快。
当您将这些值代入 Zx 和 Zy 的公式时,平方根也将被抵消,因此您将只剩下基本的算术运算。
Given
r = sqrt(x*x+y*y)
:Calculating it this way should be more accurate and faster.
When you plug these values into the formulas for Z.x and Z.y, the square root will cancel out as well, so you'll be left with only basic arithmetic operations.
我认为 1) 应该是
如果你想要真正好的性能,你可能想回到第一原则并观察
没有
sqrt()
、atan2()
或cos()
或sin()
。I think that in 1) it should be
If you want really good performance you may want to go back to first principles and observe that
No
sqrt()
,atan2()
orcos()
orsin()
.