JavaScript DFT 离散傅里叶变换
来源:互联网 发布:淘宝可以买限定皮肤吗 编辑:程序博客网 时间:2024/05/22 21:24
关于 离散傅里叶变换 DFT 以及 快速傅里叶变换 FFT 的算法可以在 算法导论第30章 或者 其他人的博客 里看到。这里不做赘述。
我们来看一种函数式的实现:
依赖
复数类
首先,建立一个复数方法类:
// complex methods// 构造函数,默认为 0complex = (x, y) => { return { x: x || 0, y: y || 0 }; }; // 从弧度构造单位复数complex.fromAngle = (angle) => complex(Math.cos(angle), Math.sin(angle));// 复数加复数complex.add = (a, b) => complex(a.x + b.x, a.y + b.y);// 复数乘复数complex.mul = (a, b) => complex(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);// 数乘复数complex.numMul = (n, c) => complex(n * c.x, n * c.y);// 复数减复数complex.minus = (a, b) => complex(a.x - b.x, a.y - b.y);
注意,这个复数乘复数与复数减复数是冗余的:
complex.numMul = (n, c) => complex.mul(complex(n), c);complex.minus = (a, b) => complex.add(a, complex.numMul(-1, b));
列表重构
关于列表重构,可以参考我的另一篇博文:JavaScript 列表重构
// array restructuringflatten = (matrix) => matrix.reduce((pre, cur) => pre.concat(cur), []);partition = (array, n) => array.reduce((pre, cur, i) => (pre[i % n] = pre[i % n] || []).push(cur) && pre, []);transpose = (matrix) => partition(flatten(matrix), matrix[0].length);
DFT & DFT的逆
这里先很不要脸地给出一行形式的代码
recursiveDFT = (a, inverse) => a.length == 1 ? a : flatten(transpose(transpose(a.reduce((pre, cur, i) => pre[i & 1].push(cur) && pre, [[], []]).map(v => recursiveDFT(v))).map((v, i) => [complex.add(v[0], complex.mul(complex.fromAngle(i * (inverse ? -2 * Math.PI / a.length : 2 * Math.PI / a.length)), v[1])), complex.minus(v[0], complex.mul(complex.fromAngle(i * (inverse ? -2 * Math.PI / a.length : 2 * Math.PI / a.length)), v[1]))]))).map(v => inverse ? complex.numMul(1 / a.length, v) : v);
传参
目前这个函数尚不类型安全,必须要有严格的传参方式才能保证不出错。
第一个参数是一个数组:
- 其中每个元素都要有 x 与 y 这两个属性。
- 数组的长度是2的幂(1, 2, 4, 8, 16, …)
第二个参数是可判定真假的值,由于存在强制转换因此不会有问题。
当第二个参数为true时,执行DFT的逆,默认为false。
测试
由于使用了ES6的语法,浏览器的支持度查询:Arrow Functions Supported
如果你的浏览器支持,你可以尽情测试:
var x = [complex(1), complex(2), complex(0), complex(0)]; // 1 + 2xvar y = [complex(3), complex(4), complex(0), complex(0)]; // 3 + 4xvar rx = recursiveDFT(x);recursiveDFT(rx, true); // almost same as xvar ry = recursiveDFT(y); recursiveDFT(ry, true); // almost same as yvar rc = rx.map((v, i) => complex.mul(v, ry[i]));recursiveDFT(rc, true); // almost same as [complex(3), complex(10), complex(8), complex(0)]
感兴趣的读者可以自行将那一行代码婊开看逻辑。
虽然我定义了几个函数(complex方法类、restructuring方法类)来处理这个问题,但是不难发现这些函数依然可以inline化组合到一起,写出一个不带分号的 One Line DFT。
0 0
- JavaScript DFT 离散傅里叶变换
- DFT(离散傅里叶变换)
- 离散傅里叶变换DFT
- 离散傅里叶变换DFT
- 离散傅里叶变换(DFT)
- DFT离散傅里叶变换
- DFT离散傅里叶变换
- 离散傅里叶变换角 DFT Angle
- 离散傅里叶变换DFT基本原理图解
- 离散傅里叶变换库,DFT,FFTW
- 2.1 离散傅里叶变换 (DFT)
- (四)连续傅里叶变换与离散傅里叶变换:离散傅里叶变换(DFT) DTFT->DFT
- 离散傅里叶变换 The Discrete Fourier Transform (DFT)
- 离散傅里叶变换(DFT)数学例子
- OpenCV学习离散傅里叶变换(DFT)
- opencv 图片的离散傅里叶变换DFT
- opencv之离散傅里叶变换(DFT)
- OpenCV离散傅里叶变换(DFT前篇)
- c++第七次作业
- 【2016.5.22】杭电女赛总结
- 使用hibernate出现no suitable Driver
- Ubuntu 16.04 使用useradd添加用户后没有家目录的解决方法
- Activiti 数据库表信息
- JavaScript DFT 离散傅里叶变换
- 运行WordCount程序
- Android Studio主题设置、颜色背景配置
- SoapUI实现Import Groovy功能
- 二分_Mode(2016swust校赛)
- JavaScript 可配置函数与柯里化
- Reverse Vowels of a String
- 暴力____Football(2016swust校赛)
- 字典树+DFS____字符矩阵(2015swust院赛)