快速傅里叶变换不是一种新的变换,而是傅里叶变换的一种快速算法,这个算法可以将普通的离散傅里叶变换(DFT)的时间复杂度O(n*n)降到O(n
log n),大大提高了傅里叶变换的速度。快速傅里叶变换算法的提出,使傅里叶变换在通信领域得到了极大地运用和发展。
在ACM中,快速傅里叶变换通常用于大数的乘法。当两个数大到连JAVA的BI都无法承受时,就该使用快速傅里叶算法了。该算法是将两个数,都写成多项式矩阵,然后对其进行离散傅里叶变换。通信领域有句很经典的话,叫做时域卷积,频域相乘。所以将两个数的多项式系数矩阵进行离散傅里叶变换后,就可以对其进行直接相乘了。将相乘后得结果再进行傅里叶逆变换(DTFT)。
我之前怎么也无法理解快速傅里叶算法,因为当时觉得太复杂了太难了,看都看不进去。但是,由于专业课,所以无可避免地会在各个课上与傅里叶变换碰面。就在上一周,我们的数字信号处理老师,花了好几节课的时间,给我们讲解了快速傅里叶算法,我当时听得很认真,并自认为听懂了。但是,当我想用自己脑子里的快速傅里叶算法求解大数相乘的题目时,却发现无从下手。我根本就不知道怎么去运用它。当时我就在想,这个算法我必须掌握它,不仅仅是因为它会出现在ACM中,更是因为它在我的专业上也占据了极其重要的地位。于是乎,我花了两天的时间,查资料,终于搞懂了这个强大的算法。我也发现有些大神写的关于FFT的文章确实非常不错,清晰易懂,我自己也收藏了,推荐给大家,大家一起学习。
JAVA代码
import java.util.Arrays;
import java.util.Scanner;
import java.util.Vector;
/**
* Created by jal on 2017/12/6 0006.
*/
public class DIT_FFT {
private static int maxn;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String numstr1 = scanner.next();
String numstr2 = scanner.next();
int len =numstr1.length()+numstr2.length();
maxn = 0;
double temp = log2(len);
double floortemp = Math.floor(temp);
if(floortemp == temp){
maxn = len;
}else {
maxn = (int)Math.pow(2,floortemp+1);
}
Complex []arra = createArray(maxn);
Complex []arrb =createArray(maxn);
Complex []arrc =createArray(maxn);
Complex []arrA = createArray(maxn);
Complex []arrB = createArray(maxn);
Complex []arrC = createArray(maxn);
char []a = numstr1.toCharArray();
int j = 0;
for(int i = a.length - 1; i >= 0; i--){
arra[j++] = new Complex(a[i] - '0');
}
j = 0;
char []b = numstr2.toCharArray();
for(int i = b.length - 1; i >= 0; i--){
arrb[j++] = new Complex(b[i] - '0');
}
//System.out.println(Arrays.toString(arra));
//invert(arra);
arrA = fft(arra);
System.out.println(Arrays.toString(arrA));
//invert(arrb);
arrB = fft(arrb);
//System.out.println(Arrays.toString(arrB));
for(int i = 0; i < arrC.length; i++){
arrC[i] = arrA[i].times(arrB[i]);
}
//System.out.println(Arrays.toString(arrC));
arrc = ifft(arrC);
Vector<Integer> vector = new Vector<>();
vector = toIntOfString(arrc);
String str = "";
char vectorCHar[] = new char[vector.size()];
for(int i = 0; i < vectorCHar.length; i++){
vectorCHar[i] = (char)(vector.get(i) + '0');
}
str =String.valueOf(vectorCHar);
str = new StringBuffer(str).reverse().toString();
//System.out.println("str:"+str);
str = trim(str);
System.out.println(str);
}
private static String trim(String value) {
int len = value.length();
int st = 0;
char[] val = value.toCharArray(); /* avoid getfield opcode */
while (