復(fù)數(shù)稱Complex Number,從英文上來看似乎它是“復(fù)雜的數(shù)”。其實并不然,它實際上指的是復(fù)合數(shù),即由實部和虛部復(fù)合而成的數(shù)。它可以用下面的公式表示:
a(Real part)+ib(Imaginary part)
這里,純實數(shù)a是實部,ib是虛部,其中,a b都是實數(shù),i是虛數(shù)。
如果我們將實部作為x軸,虛部作為y軸,復(fù)數(shù)就可以在坐標(biāo)軸上表示了,這樣的坐標(biāo)系我們稱作復(fù)數(shù)坐標(biāo)系。它和復(fù)平面上原點的連線可以表示一個向量,向量和x軸的夾角為復(fù)數(shù)的輻角theta。
實數(shù)我們大家都很熟悉,在平時生活中,常用的也都是一些實數(shù)。那么,虛數(shù)是什么呢?
虛數(shù)并不是單純的數(shù)字,如果x^2=-1,我們就將它們的解定義為+/-i,這里的i就是虛數(shù),很顯然虛數(shù)似乎并不是我們平時所使用的數(shù),因為在我們所理解的實數(shù)領(lǐng)里任何一個數(shù)進行平方之后都不可能是小于0的,但這并代表它沒有意義,我們可以換一個角度來理解虛數(shù),我們通過它可將實數(shù)擴展到復(fù)數(shù)域。
要理解虛數(shù)我們就需要先復(fù)習(xí)一下之前學(xué)習(xí)的歐拉公式:
如果,
則,
相信這里大家應(yīng)該有了發(fā)現(xiàn):
在復(fù)數(shù)域中,
復(fù)數(shù)與復(fù)指數(shù)相乘,相當(dāng)于復(fù)數(shù)對應(yīng)的向量旋轉(zhuǎn)對應(yīng)的角度。
這里就相當(dāng)于我們把1逆時針旋轉(zhuǎn)90度,就可以得到i,如果我們再逆時針旋轉(zhuǎn)90度就是-1,也就是i*i。
所以,大家也就明白了i的含義,以及為什么i的平方等于-1了。
因此,虛數(shù)i的幾何意義上是一個旋轉(zhuǎn)量。
數(shù)學(xué)是一個偉大的工具,從實數(shù)到復(fù)數(shù)的擴展是一個里程碑的進步。數(shù)學(xué)家雅克·阿達馬說,在實數(shù)域中,連接兩個真理的最短的路徑是通過復(fù)數(shù)域。
程序中如何定義復(fù)數(shù)?
在C++中,complex頭文件中定義了一個complex模板類型,用來處理復(fù)數(shù)。格式如下:
template <class T> class complex;
template<> class complex<float>;
template<> class complex<double>;
template<> class complex<long double>;
T是實部和虛部的數(shù)字的數(shù)據(jù)類型,它可以支持float、double、long double這幾種類型。
復(fù)數(shù)這個類模板有多個構(gòu)造函數(shù):
complex( const T& re = T(), const T& im = T() );
complex( const complex& other );
template<class X > complex( const complex<X>& other);
從上面復(fù)數(shù)的構(gòu)造函數(shù)可以看出,我們可以用下面的幾種方法來定義一個復(fù)數(shù):
- 根據(jù)實部和虛部的值來構(gòu)造一個復(fù)數(shù);
- 根據(jù)一個復(fù)數(shù)的值來構(gòu)造一個復(fù)數(shù);
- 從不同類型的復(fù)數(shù)構(gòu)造一個復(fù)數(shù)。
#include <iostream>
#include <complex>
int main ()
{
std::complex<float> z1(1.2, 2.3);
std::complex<float> z2(z1);
std::complex<double> z3(z2);
std::cout << z3 << 'n';
return 0;
}
結(jié)果輸出:
(1.2,2.3)
復(fù)數(shù)的運算
復(fù)數(shù)和實數(shù)一樣是可以進行+ - × /等算術(shù)運算的。假如有兩個復(fù)數(shù)z1和z2,如下:
復(fù)數(shù)的加法是將兩個復(fù)數(shù)的實部和實部相加,虛部和虛部相加:
同樣的,復(fù)數(shù)的減法是將兩個復(fù)數(shù)的實部和實部相減,虛部和虛部相減:
復(fù)數(shù)的乘法呢?因為復(fù)數(shù)也是滿足實數(shù)域的交換律、結(jié)合律以及分配律這些定理,因此,我們可以對乘法進行分解。
除法就會復(fù)雜一些,我們需要考慮將分母的復(fù)數(shù)轉(zhuǎn)成實數(shù)。該怎么進行轉(zhuǎn)換呢?在這之前,我們需要先了解共軛復(fù)數(shù),如果有兩個復(fù)數(shù)z2=c+di和z3=c-di,他們實部相同,虛部互為相反數(shù),我們稱它們互為共軛,z2是z3的共軛復(fù)數(shù),z3也是z2的共軛復(fù)數(shù)。
共軛
共軛復(fù)數(shù)有這樣的一個特性,如果兩個共軛復(fù)數(shù)相乘,它們的結(jié)果是一個實數(shù)。
因此,我們可以利用共軛復(fù)數(shù)的這個特性進行復(fù)數(shù)的除法運算。
實際上,我們在使用C++寫程序時不需要這么復(fù)雜的公式計算,complex類實際上已經(jīng)進行重載了這些操作。
complex& operator= (const T& val);
template<class X> complex& operator= (const complex<X>& rhs);
template<class T> complex<T> operator+(const complex<T>& lhs, const complex<T>& rhs);
template<class T> complex<T> operator+(const complex<T>& lhs, const T& val);
template<class T> complex<T> operator+(const T& val, const complex<T>& rhs);
template<class T> complex<T> operator-(const complex<T>& lhs, const complex<T>& rhs);
template<class T> complex<T> operator-(const complex<T>& lhs, const T& val);
template<class T> complex<T> operator-(const T& val, const complex<T>& rhs);
template<class T> complex<T> operator*(const complex<T>& lhs, const complex<T>& rhs);
template<class T> complex<T> operator*(const complex<T>& lhs, const T& val);
template<class T> complex<T> operator*(const T& val, const complex<T>& rhs);
template<class T> complex<T> operator/(const complex<T>& lhs, const complex<T>& rhs);
template<class T> complex<T> operator/(const complex<T>& lhs, const T& val);
template<class T> complex<T> operator/(const T& val, const complex<T>& rhs);
template<class T> complex<T> operator+(const complex<T>& rhs);
template<class T> complex<T> operator-(const complex<T>& rhs);
complex頭文件中已經(jīng)包含了常見的運算操作,我們通過下面的的例子來加深了解。
#include <iostream>
#include <complex>
int main ()
{
std::complex<double> z1(1, 2);
std::complex<double> z2 = std::complex<double>(3, 4);
std::cout << "z1: " << z1 << std::endl;
std::cout << "z2: " << z2 << std::endl;
std::cout << "z1+z2: " << z1+z2 << std::endl;
std::cout << "z1-z2: " << z1-z2 << std::endl;
std::cout << "z1*z2: " << z1*z2 << std::endl;
std::cout << "z1/z2: " << z1/z2 << std::endl;
std::cout << "z1+2: " <<z1 + 2.0<< std::endl;
return 0;
}
上面的例子中,我們可以使用=直接對復(fù)數(shù)進行賦值操作,還可以使用運算符對復(fù)數(shù)進行運算,而且也支持實數(shù)和復(fù)數(shù)之間的運算,其輸出結(jié)果如下:
z1: (1,2)
z2: (3,4)
z1+z2: (4,6)
z1-z2: (-2,-2)
z1*z2: (-5,10)
z1/z2: (0.44,0.08)
z1+2: (3,2)
當(dāng)然,除了上面的運算,還支持+= -= *= /=等這些運算。
complex& operator+= (const T& val);
complex& operator-= (const T& val);
complex& operator*= (const T& val);
complex& operator/= (const T& val);
template<class X> complex& operator+= (const complex<X>& rhs);
template<class X> complex& operator-= (const complex<X>& rhs);
template<class X> complex& operator*= (const complex<X>& rhs);
template<class X> complex& operator/= (const complex<X>& rhs);
同樣的,我們看下面的代碼:
#include <iostream>
#include <complex>
int main ()
{
std::complex<double> z1(1, 2);
std::complex<double> z2 = std::complex<double>(3, 4);
z1 += 2.0;
z2 -= z1;
std::cout << "z1: " << z1 << std::endl;
std::cout << "z2: " << z2 << std::endl;
return 0;
}
上面的代碼執(zhí)行結(jié)果:
z1: (3,2)
z2: (0,2)
一些其他函數(shù)
除了上面的一些運算,complex頭文件里還有一些函數(shù),我們選擇一些常見的函數(shù)來進行介紹。
- real和imag函數(shù)
- abs函數(shù)
- conj函數(shù)
- arg和polar函數(shù)
- norm函數(shù)
- exp函數(shù)
real和imag函數(shù)
我們知道了復(fù)數(shù)有實部和虛部組成,當(dāng)我們需要分開對實部和虛部處理的時候,如何取得實部和虛部的值呢?
complex頭文件定義了獲取實部(real函數(shù))和虛部(imag函數(shù))的函數(shù):
template<class T> T real (const complex<T>& x);
template<class T> T imag (const complex<T>& x);
示例:
#include <iostream>
#include <complex>
int main ()
{
std::complex<double> z1 (1,2);
std::cout << "real part: " << std::real(z1) << 'n';
std::cout << "imag part: " << std::imag(z1) << 'n';
return 0;
}
結(jié)果:
real part: 1
imag part: 2
abs函數(shù)
復(fù)數(shù)的模也就是向量的長度,它可以根據(jù)復(fù)數(shù)的實部與虛部數(shù)值的平方和的平方根的值求出。我們常利用abs函數(shù)計算信號的幅度大小。
complex頭文件中取模函數(shù)是abs,其定義:
template<class T> T abs (const complex<T>& x);
示例:
#include <iostream>
#include <complex>
int main ()
{
std::complex<double> z1 (3.0,4.0);
std::cout << "Absolute value: "<< std::abs(z1) << std::endl;
return 0;
}
結(jié)果:
Absolute value: 5
conj函數(shù)
在上面的除法運算中,我們知道,如果實部相同,虛部互為相反數(shù),那么它們互為共軛復(fù)數(shù)。complex也提供了一個函數(shù)conj便于我們求解一個復(fù)數(shù)的共軛復(fù)數(shù)。
template<class T> complex<T> conj (const complex<T>& x);
示例:
#include <iostream>
#include <complex>
int main ()
{
std::complex<double> z1 (2.0,3.0);
std::cout << "z1: " << z1 << std::endl;
std::cout << "z1 conjugate: " << std::conj(z1) << std::endl;
return 0;
}
結(jié)果:
z1: (2,3)
z1 conjugate: (2,-3)
arg函數(shù)與polar函數(shù)
arg和polar是兩個”相反“的函數(shù),這兩個函數(shù)可以進行相互轉(zhuǎn)換。arg函數(shù)作用是根據(jù)一個復(fù)數(shù)返回一個角度,而polar函數(shù)可以根據(jù)角度返回一個復(fù)數(shù)。它們在計算相位或者根據(jù)相位計算其對應(yīng)的IQ時較為常用。
template<class T> T arg (const complex<T>& x);
template<class T> complex<T> polar (const T& rho, const T& theta = 0);
示例:
#include <iostream>
#include <complex>
int main ()
{
std::complex<double> z1 (3,4);
double theta = std::arg(z1);
std::complex<double> z2 = std::polar(5.0, theta);
std::cout << "angle:" << theta << std::endl;
std::cout << "polar:" << z2 << std::endl;
return 0;
}
上面的示例先用arg函數(shù)求出對應(yīng)的theta角,然后,再用polar函數(shù)根據(jù)求出的theta角以及幅值r返回相應(yīng)的復(fù)數(shù),結(jié)果如下:
angle:0.927295
polar:(3,4)
norm函數(shù)
norm函數(shù)可以計算復(fù)數(shù)的平方和,即實部和虛部平方的和,可用于計算IQ數(shù)據(jù)的功率大小。其定義如下:
template<class T> T norm (const complex<T>& x);
示例:
#include <iostream>
#include <complex>
int main ()
{
std::complex<double> z1 (3.0,4.0);
std::cout << "z1 norm: " << std::norm(z1) << std::endl;
return 0;
}
結(jié)果:
z1 norm: 25
exp函數(shù)
complex也支持自然指數(shù),我們可以使用exp函數(shù)。通過這個函數(shù),我們就可以生成我們想要的復(fù)指數(shù)信號了。
template<class T> complex<T> exp (const complex<T>& x);
我們可以利用這個函數(shù)生成一個theta角為pi的復(fù)指數(shù)數(shù)據(jù),示例代碼:
#include <complex>
#include <iostream>
int main()
{
double pi = std::acos(-1);
std::complex<double> i(0, 1);
std::cout << std::fixed << " exp(i*pi) = " << std::exp(i * pi) << 'n';
}
運行結(jié)果如下:
exp(i*pi) = (-1.000000,0.000000)
最后
毋庸置疑,復(fù)數(shù)的提出對數(shù)學(xué)界來說是一個全新的發(fā)展,復(fù)數(shù)擴展了數(shù)的概念,讓數(shù)從一維變成了二維。復(fù)數(shù)也是現(xiàn)代數(shù)字通信行業(yè)發(fā)展的必要條件,它是數(shù)字信號處理的基礎(chǔ)。數(shù)字信號處理是一個極為抽象和復(fù)雜的學(xué)科,掌握復(fù)數(shù)的處理方法對數(shù)字信號處理應(yīng)用實為必要,因此大家一定要熟練掌握這些方法的應(yīng)用。