当前位置:首页 > JavaScript

fft js实现

2026-04-05 05:18:04JavaScript

FFT(快速傅里叶变换)的 JavaScript 实现

快速傅里叶变换(FFT)是一种高效计算离散傅里叶变换(DFT)的算法。以下是基于 Cooley-Tukey 算法的递归实现,适用于长度为 2 的幂次的输入。

递归实现

function fft(signal) {
    const N = signal.length;
    if (N === 1) return signal;

    const even = fft(signal.filter((_, i) => i % 2 === 0));
    const odd = fft(signal.filter((_, i) => i % 2 === 1));
    const result = new Array(N).fill(0).map((_, k) => {
        const angle = -2 * Math.PI * k / N;
        const exp = { re: Math.cos(angle), im: Math.sin(angle) };
        const term = {
            re: exp.re * odd[k % (N/2)].re - exp.im * odd[k % (N/2)].im,
            im: exp.re * odd[k % (N/2)].im + exp.im * odd[k % (N/2)].re
        };
        return {
            re: even[k % (N/2)].re + term.re,
            im: even[k % (N/2)].im + term.im
        };
    });
    return result;
}

非递归优化实现

递归实现虽然直观,但性能较差。以下是基于迭代的非递归实现:

fft js实现

function fftIterative(input) {
    const N = input.length;
    const log2N = Math.log2(N);
    const output = input.map((val, i) => ({ re: val, im: 0 }));

    for (let s = 1; s <= log2N; s++) {
        const m = 1 << s;
        const wm = { 
            re: Math.cos(-2 * Math.PI / m), 
            im: Math.sin(-2 * Math.PI / m) 
        };
        for (let k = 0; k < N; k += m) {
            let w = { re: 1, im: 0 };
            for (let j = 0; j < m / 2; j++) {
                const t = {
                    re: w.re * output[k + j + m/2].re - w.im * output[k + j + m/2].im,
                    im: w.re * output[k + j + m/2].im + w.im * output[k + j + m/2].re
                };
                const u = output[k + j];
                output[k + j] = { re: u.re + t.re, im: u.im + t.im };
                output[k + j + m/2] = { re: u.re - t.re, im: u.im - t.im };
                w = {
                    re: w.re * wm.re - w.im * wm.im,
                    im: w.re * wm.im + w.im * wm.re
                };
            }
        }
    }
    return output;
}

使用示例

const signal = [1, 1, 1, 1, 0, 0, 0, 0]; // 长度为 8 的示例信号(2^3)
const spectrum = fftIterative(signal);
console.log(spectrum.map(c => `${c.re.toFixed(2)} + ${c.im.toFixed(2)}i`));

注意事项

  • 输入信号长度必须是 2 的幂次(如 2, 4, 8, 16 等),否则需要补零。
  • 输出结果为复数数组,包含实部(re)和虚部(im)。
  • 如需逆变换(IFFT),可将旋转因子的角度符号取反,并最终除以 N。

性能优化建议

  • 预处理旋转因子(twiddle factors)以减少重复计算。
  • 使用 TypedArray(如 Float32Array)替代普通数组提升性能。
  • 对于大规模数据,考虑 WebAssembly 或 GPU 加速(如 WebGL)。

标签: fftjs
分享给朋友:

相关文章

js实现吸色

js实现吸色

使用Canvas实现吸色功能 通过Canvas的getImageData方法获取像素颜色数据。创建一个Canvas元素,将目标图像绘制到Canvas上,通过鼠标事件获取坐标对应的颜色值。 c…

js实现代码雨

js实现代码雨

实现代码雨效果 使用HTML5 Canvas和JavaScript可以轻松实现经典的代码雨效果。以下是完整的实现代码和说明: HTML结构 <!DOCTYPE html> <…

js分页实现

js分页实现

分页的基本原理 分页的核心是通过计算当前页码和数据偏移量,从服务器或本地数据中截取对应范围的数据进行展示。通常需要以下参数:当前页码(currentPage)、每页条数(pageSize)、总数据量(…

js实现复制功能实现

js实现复制功能实现

使用document.execCommand方法(传统方式,已逐渐被弃用) 传统方式通过document.execCommand('copy')实现复制功能,需先选中文本。以下是一个完整示例: fu…

js实现同步

js实现同步

同步与异步的概念 在JavaScript中,同步代码会按照顺序执行,每一行代码必须等待上一行代码执行完成后才能运行。异步代码则允许在等待某些操作(如网络请求)完成的同时继续执行其他代码。 实现同步的…

js实现div隐藏

js实现div隐藏

使用CSS的display属性隐藏div 通过设置元素的display属性为none,可以完全隐藏div元素。这种方法不仅隐藏元素,还会从文档流中移除,不占据页面空间。 document.getEl…