参考博文
https://blog.csdn.net/ggn_2015/article/details/68922404
https://blog.csdn.net/jgj123321/article/details/96438301
参考此博文中对多项式乘法系数的求解DFT变换的推导过程,做进一步的分析说明
1.DFT多项式乘法
B
(
x
)
B(x)
B(x) = a[0] + a[1]
×
\times
×
x
1
{x^1}
x1 + a[2]
×
\times
×
x
2
{x^2}
x2+a[3]
×
\times
×
x
3
{x^3}
x3 + a[4]
×
\times
×
x
4
{x^4}
x4 + a[5]
×
\times
×
x
5
{x^5}
x5+ a[6]
×
\times
×
x
6
{x^6}
x6 + a[7]
×
\times
×
x
7
{x^7}
x7
C
(
x
)
C(x)
C(x) = b[0] + b[1]
×
\times
×
x
1
{x^1}
x1 + b[2]
×
\times
×
x
2
{x^2}
x2+b[3]
×
\times
×
x
3
{x^3}
x3 + b[4]
×
\times
×
x
4
{x^4}
x4 + b[5]
×
\times
×
x
5
{x^5}
x5+ b[6]
×
\times
×
x
6
{x^6}
x6 + b[7]
×
\times
×
x
7
{x^7}
x7
首先我们已知系数可以求得任意的点值;
那么如何用点值反求系数呢?为什么要用点值反求系数呢?
计算
B
(
x
)
B(x)
B(x)
×
\times
×
C
(
x
)
C(x)
C(x)的表达式的复杂程度:O(n
×
\times
×m),就是每一个系数都要进行相乘来获取方程不同幂的系数。用点值法可以减少乘法的计算复杂度,请看如何用分治的思想求解
可将系数看作是一组方程的解,学过线性代数的都清楚
A
x
=
b
Ax = b
Ax=b;
x就是所求的系数解,
b
b
b为
f
(
x
)
f(x)
f(x)对应的值,要求所有系数有唯一解的条件就是
r
(
A
:
b
)
r(A:b)
r(A:b) = 系数
a
a
a的个数
n
n
n, 只需要构造一个矩阵
A
A
A的秩为
n
n
n就可以得到唯一的以组系数解,可以看出
[
1
1
1
1
1
x
1
1
x
2
1
x
3
1
⋯
x
n
1
x
1
2
x
2
2
x
3
2
⋯
x
n
2
⋯
⋯
⋯
⋯
x
n
k
x
1
n
x
2
n
x
3
n
⋯
x
n
n
]
\begin{bmatrix} 1&1&1&1&1\\ {x_1^1}&{x_2^1}&{x_3^1}&{\cdots}&{x_n^1}\\ {x_1^2}&{x_2^2}&{x_3^2}&{\cdots}&{x_n^2}\\ {\cdots}&{\cdots}&{\cdots}&{\cdots}&{x_n^k}\\ {x_1^n}&{x_2^n}&{x_3^n}&{\cdots}&{x_n^n} \end{bmatrix}
⎣⎢⎢⎢⎢⎡1x11x12⋯x1n1x21x22⋯x2n1x31x32⋯x3n1⋯⋯⋯⋯1xn1xn2xnkxnn⎦⎥⎥⎥⎥⎤
其中 x 1 x_1 x1、 x 2 x_2 x2、 x 3 x_3 x3、 ⋯ \cdots ⋯、 x n x_n xn为不相等的取值,根据范德蒙行列式的性质,该行列式的值为非零值,构成的矩阵可逆。 r ( A : b ) r(A:b) r(A:b)= 系数 a a a的个数 n n n。
如何构造 n n n个 x x x的值,成了当前需要思考的问题,并且 x x x取不同值的时候,尽可能的减少与系数的相乘次数,因此就需要一组有规律的 x x x的值来尽可能减少求值次数。
e
2
π
k
i
/
n
=
w
n
k
{e^{2\pi ki/n}} = w_n^k
e2πki/n=wnk其中
(
k
=
1
、
2
、
3
、
⋯
、
n
)
(k=1、2、3、\cdots、n)
(k=1、2、3、⋯、n)
将用
w
n
k
w_n^k
wnk一组复数平面内的有规律的
x
x
x的值求解。
w
n
k
w_n^k
wnk有何规律?
w
n
k
=
w
n
2
k
2
w_n^k = w_{\frac{n}{2}}^{\frac{k}{2}}
wnk=w2n2k
欧拉公式
e
i
x
=
c
o
s
x
+
i
×
s
i
n
x
e^{ix}=cosx+i×sinx
eix=cosx+i×sinx
w
n
k
+
n
2
=
e
π
k
i
n
×
e
π
i
=
−
w
n
k
w_n^{k+\frac{n}{2}}={{\rm{e}}^{\frac{{{\rm{\pi }}k{\rm{i}}}}{{\rm{n}}}}}\times{{\rm{e}}^{{\rm{\pi i}}}}=-w_n^{k}
wnk+2n=enπki×eπi=−wnk
可以看出
n
n
n个点的取值不同,获取的
w
n
k
w_n^k
wnk不一样
并且按理我们可以通过
w
n
1
w_n^1
wn1求得
w
n
1
+
n
2
w_n^{1+\frac{n}{2}}
wn1+2n,可以通过
w
n
2
1
w_{\frac{n}{2}}^1
w2n1求出
w
n
2
w_n^2
wn2
B
(
x
)
B(x)
B(x) = a[0] + a[1]
×
\times
×
x
1
{x^1}
x1 + a[2]
×
\times
×
x
2
{x^2}
x2+a[3]
×
\times
×
x
3
{x^3}
x3 + a[4]
×
\times
×
x
4
{x^4}
x4 + a[5]
×
\times
×
x
5
{x^5}
x5+ a[6]
×
\times
×
x
6
{x^6}
x6 + a[7]
×
\times
×
x
7
{x^7}
x7转换成
A
0
(
x
)
A_0(x)
A0(x) = a[0] + a[2]
×
\times
×
x
{x}
x + a[4]
×
\times
×
x
2
{x^2}
x2 + a[6]
×
\times
×
x
3
{x^3}
x3
A
1
(
x
)
A_1(x)
A1(x) = a[1] + a[3]
×
\times
×
x
1
{x^1}
x1 + a[5]
×
\times
×
x
2
{x^2}
x2 + a[7]
×
\times
×
x
3
{x^3}
x3
请看如何求解
B
(
x
)
B(x)
B(x)=
A
0
(
x
2
)
{A_0}({x^2})
A0(x2)+
x
×
A
1
(
x
2
)
x\times{A_1}({x^2})
x×A1(x2)
B
(
w
8
1
)
B({w_8}{^1})
B(w81) =
A
0
(
w
4
1
)
{A_0}({w_4}{^1})
A0(w41)+
w
8
1
×
A
1
(
w
4
1
)
{w_8}{^1}\times{A_1}({w_4}{^1})
w81×A1(w41)(
w
n
k
=
w
n
2
k
2
w_n^k = w_{\frac{n}{2}}^{\frac{k}{2}}
wnk=w2n2k性质)
B
(
w
8
5
)
B({w_8}{^5})
B(w85) =
A
0
(
w
4
1
)
{A_0}({w_4}{^1})
A0(w41)-
w
8
1
×
A
1
(
w
4
1
)
{w_8}{^1}\times{A_1}({w_4}{^1})
w81×A1(w41)(
w
n
k
+
n
2
=
e
π
k
i
n
×
e
π
i
=
−
w
n
k
w_n^{k+\frac{n}{2}}={{\rm{e}}^{\frac{{{\rm{\pi }}k{\rm{i}}}}{{\rm{n}}}}}\times{{\rm{e}}^{{\rm{\pi i}}}}=-w_n^{k}
wnk+2n=enπki×eπi=−wnk性质)
对应只需要求解
B
(
w
8
1
)
B(w_8^1 )
B(w81)、
B
(
w
8
2
)
B(w_8^2 )
B(w82)、
B
(
w
8
3
)
B(w_8^3 )
B(w83)、
B
(
w
8
4
)
B(w_8^4 )
B(w84)即可
那么
A
0
(
w
4
1
)
A_0 (w_4^1 )
A0(w41)、
A
0
(
w
4
2
)
A_0 (w_4^2 )
A0(w42)、
A
0
(
w
4
3
)
A_0 (w_4^3 )
A0(w43)、
A
0
(
w
4
4
)
A_0 (w_4^4 )
A0(w44)又该如何求解呢?
因为 A 0 ( x ) A_0 (x) A0(x)也可以一样将系数分为奇偶项拆分
A 0 ( x ) = A 00 ( x 2 ) + x × A 01 ( x 2 ) A_0 (x)= A_{00} (x^2 )+x× A_{01} (x^2 ) A0(x)=A00(x2)+x×A01(x2) 得到第二层
A
0
(
w
4
1
)
=
A
00
(
w
2
1
)
+
w
4
1
×
A
01
(
w
2
1
)
A_0 (w_4^1 )= A_{00} (w_2^1 )+w_4^1× A_{01} (w_2^1 )
A0(w41)=A00(w21)+w41×A01(w21)
同理只需要求解
A
0
(
w
4
1
)
、
A
0
(
w
4
2
)
A_0 (w_4^1 )、A_0 (w_4^2 )
A0(w41)、A0(w42)
A
00
(
x
)
=
A
000
(
x
2
)
+
x
×
A
001
(
x
2
)
A_{00}(x)=A_{000} (x^2 )+x× A_{001} (x^2 )
A00(x)=A000(x2)+x×A001(x2) 得到第三层
A
00
(
w
2
1
)
=
A
000
(
w
1
1
)
+
w
2
1
×
A
001
(
w
1
1
)
A_{00} (w_2^1 )= A_{000} (w_1^1 )+w_2^1× A_{001} (w_1^1 )
A00(w21)=A000(w11)+w21×A001(w11)
通过欧拉函数将复数平面内不同二次项函数值的求解过程做了递归分析
这样就可以使得我们求解乘法减少为
n
l
o
g
n
nlogn
nlogn次,并计算出n个不同的点值
void fft_example( COMPLEX *a,int n,int dft)
{
for(int i=0;i< n;i++)
{
if(i < reverseVal[i])
swap(A_ref[i],A_ref[reverseVal[i]]); //系数反转完毕
//系数翻转后的默认为a[0] a[4] a[2] a[6] a[1] [5] a[3] a[7]
//通过计算得到了A000,A001,A010,A011,A100,A101,A110,A111
//通过计算得到了A00(1/2),A00(1),A01(1/2),A01(1),A10(1/2),A10(1),A11(1/2),A(1)
//通过计算得到了A0(1/4),A0(2/4),A0(3/4),A0(1),A1(1/4),A1(2/4),A1(3/4),A1(1)
//通过计算得到了A(1/8).....
for(int step=1;step <n;step<<=1)
{
COMPLEX Wn= exp(COMPLEX(0,dft*PI/step)); //计算合并求y值的奇数项x取值;
for(int j= 0;j<n;j+=step<<1) //划分的n中的所有小组;
{
COMPLEX Cn(1,0);
for(int k=j;k<j+step;k++)
{
COMPLEX x = a[k];
COMPLEX y = Cn*a[k+step]; //这个就是wn的二分定理;
a[k] = x +y;
a[k+step] = x-y; //蝴蝶算法的信息合并;
Cn *= Wn; //每一个小组计算一次后需要放大
}
}
}
}
if(dft == -1)
{
for(int i=0;i<n;i++) a[i]/=n;
}
}
void FFT(FFT_HANDLE *hfft, COMPLEX *TD2FD)
{
int i,j,k,butterfly,p;
int power = NumberOfBits(hfft->count); //对应采样点数对应最大的分治次数step
/*蝶形运算*/
for(k = 0; k < power; k++) //k对应step层;
{
for(j = 0; j < 1<<k; j++)
{
butterfly = 1 << (power-k); //step为0的时候就是3-0=3; butterfly =8
p = j * butterfly; //p=0
int s = p + butterfly / 2; //s=4 ;
for(i = 0; i < butterfly/2; i++)
{
COMPLEX t = TD2FD[i + p] + TD2FD[i + s];
TD2FD[i + s] = (TD2FD[i + p] - TD2FD[i + s]) * hfft->wt[i*(1<<k)];
TD2FD[i + p] = t;
//a[0]与a[4],a[1]与a[5],a[2]与a[6] 当step为1的时候
}
}
}
/*重新排序*/
for (k = 0; k < hfft->count; k++)
{
int r = BitReverise(k, power);
if (r > k)
{
COMPLEX t = TD2FD[k];
TD2FD[k] = TD2FD[r];
TD2FD[r] = t;
}
}
} //最初没有进行翻转,最终得出的结果为A(1/8),A(5/8),A(2/8)、、、、需要翻转。