FFT快速乘法 - 从信号处理到大数计算的革命
026突破乘法速度极限:FFT革命
5W1H 发明者故事
Who(何人)- 发明者是谁?
核心发明者:詹姆斯·库利(James W. Cooley,1926-2016)与约翰·图基(John W. Tukey,1915-2000)
背景:
- 库利是IBM沃森研究中心的数学家,专注于数值计算;
- 图基是普林斯顿大学统计学教授,同时在贝尔实验室任职,是统计学界的传奇人物(他还是"bit"和"software"两个词的发明者)。
- 两人因核武器监测的需要而相遇,合作写出了改变计算机科学史的短短六页论文。
更早的渊源:历史学家后来发现,高斯(Gauss)在1805年手稿中已有类似思想,但从未发表。卡尔·龙格(Carl Runge,1903年)和赫尔曼·科尼希(Hermann König)也有相关工作。然而是库利-图基在计算机时代将其系统化并推广。
When(何时)- 什么时候发明的?
时间:1965年,论文发表于《Mathematics of Computation》第19卷
时代背景:
- 冷战高峰期,美苏核武器竞赛激烈;
- 1963年,肯尼迪政府正在谈判《部分禁止核试验条约》,需要用地震仪区分地震与核爆炸,这要求极高速度的傅里叶分析;
- IBM 7094计算机刚刚出现,但计算傅里叶变换的DFT(离散傅里叶变换)仍需 O(n²) 时间,处理1000个点需要百万次运算,速度远不够用;
- 图基在一次科学顾问委员会会议上提出了快速算法的思路,库利将其实现为计算机程序,整个过程仅用了约6周。
Where(何地)- 在哪里发明的?
地点:美国纽约约克镇高地,IBM托马斯·J·沃森研究中心(IBM T. J. Watson Research Center)
背景环境:这里是1960年代最顶尖的工业研究实验室之一,汇聚了数学、物理、计算机的世界级人才。图基在普林斯顿提出思路,库利在Watson中心完成编程实现,两地协作产生了这项发明。
What(何事)- 发明了什么?
算法:Cooley-Tukey FFT(快速傅里叶变换)
核心思想:分治法(Divide and Conquer)
将长度为 N 的DFT分解为两个长度为 N/2 的DFT:
DFT_N[k] = DFT_偶数下标[k] + W_N^k * DFT_奇数下标[k]
其中 W_N = e^(-2πi/N) 是旋转因子(twiddle factor)。
复杂度突破:
- 朴素DFT:O(n²) 次复数乘法
- Cooley-Tukey FFT:O(n log n) 次
- 对 n=1024:从 1,048,576 次降为 10,240 次,快了100倍
与多项式乘法的联系 :
多项式乘法的朴素算法是 O(n²)(卷积)。FFT可将多项式从系数表示转为点值表示(O(n log n)),在点值域做逐点乘法(O(n)),再用逆FFT转回系数(O(n log n)),总复杂度 O(n log n)。大整数乘法可视为十进制多项式乘法,因此也受益于FFT。
Why(何因)- 为什么发明?
直接动机:监测苏联核试验------美国需要实时分析来自全球地震台网的地震波形,判断是自然地震还是地下核爆炸,这需要对大量时间序列做频谱分析。
计算瓶颈:当时分析一段地震数据需要数小时,政策决策完全不可能基于实时数据。
更广泛的影响:
- 信号处理:音频/图像压缩(MP3、JPEG均基于FFT思想)
- 大数计算:密码学、大整数运算
- 科学计算:偏微分方程数值解、量子化学
- 通信:OFDM(现代4G/5G的核心调制技术)
How(何果)- 如何实现?有什么影响?
蝶形运算(Butterfly Operation):FFT的基本计算单元
A' = A + W * B
B' = A - W * B
递归结构(以8点FFT为例):
8点FFT
├── 4点FFT(偶数位:x[0],x[2],x[4],x[6])
│ ├── 2点FFT(x[0],x[4])
│ └── 2点FFT(x[2],x[6])
└── 4点FFT(奇数位:x[1],x[3],x[5],x[7])
├── 2点FFT(x[1],x[5])
└── 2点FFT(x[3],x[7])
历史影响:
- 被列为20世纪十大算法之一(SIAM评选)
- Knuth在TAOCP第二卷4.3.3节专门分析了FFT在多项式/大数乘法中的应用
- 图基去世后,美国国家科学院院刊以整版悼念,称其为"统计学的达·芬奇"
自然语言需求定义
需求名称:基于Cooley-Tukey FFT实现多项式乘法与大整数乘法
功能需求
- FFT正变换:将长度为2的幂次的实数/复数数组变换到频域(Cooley-Tukey基-2时域抽取算法)
- FFT逆变换:将频域结果变换回时域,并做1/N归一化
- 多项式乘法:将两个系数数组表示的多项式相乘,返回积多项式的系数
- 大整数乘法:将两个用十进制表示的大整数(字符串或数组形式)相乘,处理进位
- 辅助功能:下一个2的幂次计算(用于FFT补零)
验收标准
| 编号 | 测试场景 | 预期结果 | 验证方式 |
|---|---|---|---|
| 1 | 多项式 (1+x) × (1+x+x²) | 1+2x+2x²+x³ | 系数数组 [1,2,2,1] |
| 2 | 多项式 (1+x)² | 1+2x+x² | 系数数组 [1,2,1] |
| 3 | 多项式 (2+3x) × (1+4x) | 2+11x+12x² | 系数数组 [2,11,12] |
| 4 | 大整数 1234 × 5678 | 7006652 | 与直接乘法比较 |
| 5 | 大整数 999 × 999 | 998001 | 与直接乘法比较 |
| 6 | 多项式与常数相乘:(1+x+x²) × 3 | 3+3x+3x² | 系数数组 [3,3,3] |
| 7 | 零多项式相乘 | 零多项式 | 系数全为0 |
C语言实现文件
对应文件 : fft_multiply.c
编译运行:
bash
gcc -std=c99 -Wall -o /tmp/fft_multiply_test fft_multiply.c -lm
./fft_multiply_test