加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

從一維到二維,C++復(fù)數(shù)運算總結(jié)

04/27 11:25
4767
閱讀需 21 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

復(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)用。

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風(fēng)險等級 參考價格 更多信息
KSZ9031MNXIA-TR 1 Microchip Technology Inc DATACOM, ETHERNET TRANSCEIVER, QCC64
$41.55 查看
LAN8710A-EZC-ABC 1 Microchip Technology Inc Ethernet Transceiver

ECAD模型

下載ECAD模型
$1.55 查看
TJA1042T/3,118 1 NXP Semiconductors TJA1042 - High-speed CAN transceiver with Standby mode SOIC 8-Pin

ECAD模型

下載ECAD模型
$1.51 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜