📄 2.cpp
字号:
#include <iostream.h>
#include <cmath>
class complex //编写复数类
{
public:
complex(double r=1,double i=1):real(r),imag(i){}//构造函数,实现初始化
// complex (double r) {real= r;imag=0;}//转换构造函数
friend complex operator+(complex &c1,complex &c2); //重载+运算
friend complex operator-(complex &c1,complex &c2);//重载-运算
friend complex operator*(complex &c1,complex &c2);//重载×运算
friend complex operator/(complex &c1,complex &c2);//重载/运算
friend complex operator*(complex &c2,double d);//重载×运算,可以实现复数和实数相乘
complex conjugate();//求复数共轭函数
complex negconjugate();//求复数负共轭函数
void setinitial (double ,double);//给复数设置值函数
double mod();//复数求模函数
void display();//复数的现实函数,即输出函数
friend int constel(complex &c1);
private:
double real;//私有变量 ,复数的实部
double imag;//私有变量, 复数的虚部
};
/******************************************************************************
以下定义实现复数类的函数
****************************************************************************/
complex operator+(complex &c1,complex & c2)//加
{
return complex(c1.real+c2.real,c1.imag+c2.imag);//前面的complex不能忽略,注意!!!
}
complex operator-(complex &c1,complex & c2)//减
{
return complex(c1.real-c2.real,c1.imag-c2.imag);
}
complex operator*(complex &c1,complex &c2)//乘
{
return complex(c1.real*c2.real-c1.imag*c2.imag,c1.real*c2.imag+c1.imag*c2.real);
}
complex operator/(complex &c1,complex &c2)//除
{
return complex((c1.real*c2.real-c1.imag*c2.imag)/ sqrt (c2.imag*c2.imag+c2.real*c2.real),(c1.real*c2.imag+c1.imag*c2.real)/ sqrt (c2.imag*c2.imag+c2.real*c2.real));
}
complex operator*(complex &c2,double d)//复数和实数的乘
{
return complex(d*c2.real,d*c2.imag);
}
void complex::display()//复数显示
{
cout<<"("<<real<<","<<imag<<"i"<<")"<<endl;
}
complex complex::conjugate()//求复数的共轭
{
return complex(real,-imag);
}
complex complex::negconjugate()//求复数的负共轭
{
return complex(-real,imag);
}
void complex::setinitial (double r ,double i)//复数对象的赋值
{
real=r;
imag=i;
}
double complex::mod()//复数求模
{
return((double)sqrt((real*real)+(imag*imag)));
}
int constel(complex &c1) //星座解调函数
{
if(c1.real==0)
{
if(c1.imag==1) return 3;
else return 5;
}
else if(c1.imag==0)
{
if(c1.real==1) return 0;
else return 6;
}
else if(c1.real>0)
{
if(c1.imag>0) return 1;
else return 4;
}
else if(c1.imag<0)
{
if(c1.real<0) return 7;
else return 2;
}
}
/*******************************************************************************
设置全局变量,生成m序列
******************************************************************************/
int A[42];//定义全局变量A数组,在程序中,这个数组表示的是我们得到的伪随机序列
int B[42];
double biterror,symerror;
double ber,symer;
void msequence() //15位M序列发生器函数
{ int i,j;
int a[5]={1,0,1,0,1};
for(j=0;j<45;j++)
{
int temp=(a[0]+a[3])%2;
if(j%15==0) cout<<endl;
A[j]=a[4];
for(i=4;i>=0;i--)
a[i]=a[i-1];
a[0]=temp;
}
}
complex t[14];//复数对象数组,便于存放每一时刻调制后发送的信号值
complex dt[14];//复数对象数组,便于存放每一时刻解调后发送的信号值
/********************************************************************
主函数
***************************************************************/
void main()
{
// void coding();
void decoding(complex &c1,complex &c2);//解调函数的声明
void constellation(complex &c1);
complex c1,c2,c3,c4;//设置复数对象,便于调制和星座映射
int i,j,k,d,g,temp;
double Z=sqrt(2)/2;//8PSK星座图中某些点的坐标值
msequence();//调用m序列函数发生器产生一个15位的m序列
for(i=0;i<42;i++)
cout<<A[i];
cout<<endl;//先将产生的序列输出,按顺序输出
for(j=0;j<7;j++)//本程序中共有45个比特的数据,我们每次需要顺序取出6个比特来发射,故循环七次
{
for(i=0;i<6;i++)//顺序取出6个比特来发射
cout<<A[i];
cout<<endl;//输出这6个比特便于检测
d=A[0]*4+A[1]*2+A[2]*1;//取每3个比特来进行8PSK调制,先将二进制转化为十进制,该步是为了便于写后面的选择语句
g=A[3]*4+A[4]*2+A[5]*1;//d为前3个输出的比特表示的十进制数,对应我们的X1;g为后3个输出的比特表示的十进制数,对应我们的X2;
for ( i=0;i<6;i++)//实现循环左移操作
{
temp=A[0] ;//先将数组头一个元素的值保留下来
for (k=0;k<42;k++) //使用++操作,使数组元素逐一往左移动
{
A[k]=A[k+1];
}
A[41]=temp;//再将原先数组头一个元素的值放到新数组的最后一个,实现数组元素的循环
}
//for(i=0;i<42;i++)//每取6个比特后就将数组前移,便于后面取数
// {
// A[i]=A[i+6];
// }
//8PSK中的映射关系,采用GRAY编码,这种编码可以使噪声引起的误差在3个比特的码元中仅出现一个比特的错
switch(d)//X1的8PSK映射;
{
case(0):c1.setinitial(1,0);break;
case(1):c1.setinitial(Z ,Z );break;
case(2):c1.setinitial(-Z ,Z );break;
case(3):c1.setinitial(0 ,1 );break;
case(4):c1.setinitial(Z ,-Z );break;
case(5):c1.setinitial(0 ,-1 );break;
case(6):c1.setinitial(-1,0);break;
case(7):c1.setinitial(-Z,-Z );break;
}
cout<<j<<"时刻"<<endl;//t时刻第一根天线上输出的是X1
cout<<"X=";
c1.display(); //调制后星座映射情况显示
switch(g)//X2的8PSK映射;
{
case(0):c2.setinitial(1,0);break;
case(1):c2.setinitial(Z ,Z );break;
case(2):c2.setinitial(-Z ,Z );break;
case(3):c2.setinitial(0 ,1 );break;
case(4):c2.setinitial(Z ,-Z );break;
case(5):c2.setinitial(0 ,-1 );break;
case(6):c2.setinitial(-1,0);break;
case(7):c2.setinitial(-Z,-Z );break;
}
cout<<"Y=";//t时刻第二根天线上输出的是X2
c2.display();
t[2*j]=c1;//将调制星座映射变量放入复数对象数组中
t[2*j+1]=c2;//将调制星座映射变量放入复数对象数组中
cout<<j<<"+T时刻"<<endl;//t+T时刻第一根天线上输出的是-X2*
cout<<"X=";
c3=c2.negconjugate();//复数的负共轭
c3.display();
cout<<"Y=";//t+T时刻第二根天线上输出的是X1*
c4=c1.conjugate();//复数的共轭
c4.display();
}
cout<<"************************************************"<<endl;
cout<<" 开始译码 "<<endl;
cout<<"************************************************"<<endl;
for(j=0;j<7;j++)//分为7组,每组两个调制符号,即x1和x2
{
t[2*j].display();
t[2*j+1].display();
decoding(t[2*j],t[2*j+1]);//每次解调两个符号,共解调7次
}
for (j=0;j<14;j++)
{
constellation(dt[j]);
}
cout<<"发送数据为A:"<<endl;
for(j=0;j<42;j++)
cout <<A[j]<<" ";
cout<<"接收数据为B:"<<endl;
for(j=0;j<42;j++)
cout <<B[j]<<" ";
for(j=0;j<42;j++)
{
if(A[j]!=B[j])
biterror++;
}
ber=biterror/42;
cout<<"误码率为:"<<ber<<endl;
}
/*********************************************************************
模拟信道 并接收 解调函数
********************************************************************/
void decoding(complex &c1,complex &c2) //信道加扰 译码函数
{
static int u;
complex s1,s2,h1(1,1),h2(2,2);//s为判决变量,h为信道衰落系数
complex r1,r2,n1(0,1),n2(0,1);//r为接收信号,n为信道复噪声
r1=h1*c1+h1*c2+n1;
r2=h1*c2.negconjugate()+h1*c1.conjugate()+n2;
int k=0,p=0;
/*****************************************************
s1=r1*h1.conjugate()+r2.conjugate()*h2;
s2=r1*h2.conjugate()-r2.conjugate()*h1;
*******************************************************/
s1=c1*(h1.mod()*h1.mod()+h2.mod()*h2.mod())+h1.conjugate()*n1+h2*n2.conjugate();
s2=c2*(h1.mod()*h1.mod()+h2.mod()*h2.mod())+h1*n2.negconjugate()+h2.conjugate()*n1;
double min1,min2;
min1=(t[0]-s1).mod()*(t[0]-s1).mod();//min1为s1的比较变量
min2=(t[0]-s2).mod()*(t[0]-s2).mod();//min2为s2的比较变量
for(int i=1;i<14;i++)//将原来调制的所有变量一起拿来比较,找出最小的平方欧式距离
{
if((t[i]-s1).mod()*(t[i]-s1).mod()<min1)
{min1=(t[i]-s1).mod()*(t[i]-s1).mod();
k=i;//保存判断接收信号判决变量s1欧式距离的最小值时的数组下标
}
if((t[i]-s2).mod()*(t[i]-s2).mod()<min2)
{min2=(t[i]-s2).mod()*(t[i]-s2).mod();
p=i;//保存判断接收信号判决变量s2欧式距离的最小值时的数组下标
}
}
cout<<u<<" 时刻c1的译码输出为: ";
t[k].display();
dt[2*u]=t[k];
cout<<u<<" 时刻c2的译码输出为: ";
t[p].display();
dt[2*u+1]=t[p];
u++;
}
/********************************************************************
星座图的逆变换,即星座解调
******************************************************************/
void constellation(complex &c1)
{
int c=constel(c1);
int t[3];
switch(c)
{
case(0): {t[0]=0;t[1]=0;t[2]=0;break;}
case(1): {t[0]=0;t[1]=0;t[2]=1;break;}
case(2): {t[0]=0;t[1]=1;t[2]=0;break;}
case(3): {t[0]=0;t[1]=1;t[2]=1;break;}
case(4): {t[0]=1;t[1]=0;t[2]=0;break;}
case(5): {t[0]=1;t[1]=0;t[2]=1;break;}
case(6): {t[0]=1;t[1]=1;t[2]=0;break;}
case(7): {t[0]=1;t[1]=1;t[2]=1;break;}
}
static int i=0;
B[i]=t[0];
B[i+1]=t[1];
B[i+2]=t[2];
i=i+3;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -