搜索
bottom↓
回复: 13

一个简单的算法:复数求相位角

[复制链接]

出10入23汤圆

发表于 2017-3-12 14:02:26 | 显示全部楼层 |阅读模式
本帖最后由 zouzhichao 于 2017-3-12 14:16 编辑

先贴出复数结构定义体,很容易理解:


求相位,那不是很简单么?先贴第一个函数


当然,当你看到第二个函数,就会发现第一个函数有问题了:


这个时候,不会有问题了吧?其实不然,那你看看第三个函数:


当然,还有第四个函数,这个与第三个类似:


其实还有第五个函数,比第三第四又好一些:


源码:
  1. typedef struct tagCOMPLEX {
  2.         float real;
  3.         float image;
  4. }COMPLEX;

  5. float cal(const COMPLEX* dat) {
  6.         return atan(dat->image / dat->real);
  7. }

  8. float cal(const COMPLEX* dat) {
  9.         float phase = atan(dat->image / dat->image);
  10.         if (dat->real < 0.0f) {
  11.                 phase += 3.1415926f;
  12.         }
  13.         if (phase > 3.1415926f) {
  14.                 phase -= 3.1415926f * 2.0f;
  15.         }
  16.         return phase;
  17. }

  18. float cal(const COMPLEX* dat) {
  19.         float amp, cos_x;
  20.         amp = dat->real * dat->real + dat->image * dat->image;
  21.         amp = inv_sqrt(amp);
  22.         cos_x = dat->real * amp;
  23.         amp = acos(cos_x);
  24.         return dat->image > 0? amp : -amp;
  25. }

  26. float cal(const COMPLEX* dat) {
  27.         float amp, sin_x;
  28.         amp = dat->real * dat->real + dat->image * dat->image;
  29.         amp = inv_sqrt(amp);
  30.         sin_x = dat->image * amp;
  31.         amp = asin(sin_x);
  32.         if (dat->real < 0.0f) {
  33.                 amp += 3.1415926f;
  34.         }
  35.         if (amp > 3.1415926f) {
  36.                 amp -= 3.1415926f * 2.0f;
  37.         }
  38.         return amp;
  39. }

  40. float cal(const COMPLEX* dat) {
  41.         float amp, cos_x, sin_x;
  42.         amp = dat->real * dat->real + dat->image * dat->image;
  43.         amp = inv_sqrt(amp);
  44.         cos_x = dat->real * amp;
  45.         sin_x = dat->image * amp;
  46.         if (fabs(cos_x) < fabs(sin_x)) {
  47.                 amp = acos(cos_x);
  48.                 return sin_x > 0? amp : -amp;
  49.         }
  50.         amp = asin(sin_x);
  51.         if (cos_x < 0.0f) {
  52.                 amp += 3.1415926f;
  53.         }
  54.         if (amp > 3.1415926f) {
  55.                 amp -= 3.1415926f * 2.0f;
  56.         }
  57.         return amp;
  58. }
复制代码


有必要说明一下,后面几个函数用到了一个叫inv_sqrt的倒数平方根函数,这个函数有个快速算法,故居很多人都有收藏,就不贴出来

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出10入23汤圆

 楼主| 发表于 2017-3-12 14:20:49 | 显示全部楼层
一个快速浮点开方程序,据说能比float sqrt(x)快4倍

出0入93汤圆

发表于 2017-3-12 14:25:10 | 显示全部楼层
你确定第一个是正确的?这个“算法”算出1+i和-1-i的相位一样??? 都是pi/4???

出10入23汤圆

 楼主| 发表于 2017-3-12 14:34:10 | 显示全部楼层
takashiki 发表于 2017-3-12 14:25
你确定第一个是正确的?这个“算法”算出1+i和-1-i的相位一样??? 都是pi/4???

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2017-3-12 14:39:57 | 显示全部楼层
有个函数叫 atan2

出10入23汤圆

 楼主| 发表于 2017-3-12 14:44:58 | 显示全部楼层

这是一个好函数

出0入0汤圆

发表于 2017-3-12 14:46:04 | 显示全部楼层

顶这个方位角,哈哈哈

出0入0汤圆

发表于 2017-3-12 15:16:19 | 显示全部楼层
多块?F407如果普通sqrt,168MHz时钟3微秒左右得到结果,arm_sqrt调用浮点硬件330ns左右

出0入0汤圆

发表于 2017-3-12 23:22:46 来自手机 | 显示全部楼层
atan2能算90度的整倍数么?这时的输入值接近无限大了!所以还是换成正余弦算避免90度的问题。

出90入0汤圆

发表于 2017-3-13 11:09:15 | 显示全部楼层
第二个函数:float phase = atan(dat->image / dat->image);
没写错吗?

出0入0汤圆

发表于 2017-3-13 11:17:31 | 显示全部楼层
随机验证过可靠性么?

出10入23汤圆

 楼主| 发表于 2017-3-13 11:18:32 来自手机 | 显示全部楼层
xuyapple 发表于 2017-3-13 11:09
第二个函数:float phase = atan(dat->image / dat->image);
没写错吗?

写错了,image/real

出0入93汤圆

发表于 2017-3-14 07:05:58 | 显示全部楼层
XA144F 发表于 2017-3-12 23:22
atan2能算90度的整倍数么?这时的输入值接近无限大了!所以还是换成正余弦算避免90度的问题。 ...

标准的IEEE 754中是有无穷大的,因此atan2能算90度的整倍数。比如:atan2(1, 0) = PI / 2

出0入0汤圆

发表于 2017-4-17 18:19:20 | 显示全部楼层
本帖最后由 xycfwrj 于 2017-4-17 18:31 编辑

给一个我写的基于dsp的近似计算的代码,其中_rcpsp是求倒数,需要替换
                        float den = fx + fy;
                        float num = fx - fy;
                        rcp = _rcpsp(den);   //= 1.f/den,也可以用快速算法
                        rcp = rcp * (2.f - den * rcp);  //

                        theta = 1.f - num * rcp;

                        if (fx<0.f)
                                theta = theta + 2.f;
                        if (fy<0.f)
                                theta = -theta;
                        theta = theta * PI/4;
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-19 23:46

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表