信息论与编码学上机实习报告

时间:2024.4.1

信息论与编码上机实习

学生姓名:         XX             

    级:       XXXXX        

    号:       XXXXXXXX        

指导老师:          XX           

实验一 字典编码

一、实验题目

1、输入:

①The Lempel Ziv algorithm can compress the English text by about fifty five percent.

②The cat cannot sit on the canopy of the car.

2、输出:经过字典编码后生成的码字。

二、实验目的

1、理解和掌握字典编码的原理;

2、理解和掌握字典译码的原理。

三、算法设计

四、程序分析

1.用结构体存储字符串及其对应的字典编码;

2.用链表存储整个字典;

3.dictionary()子函数的作用是将当前字符同链表中的字典相比较,若存在与字典中,则向结构体的数组里存放发送信息的下一位,直到当前数组中的字符串和链表字典不相等则将该字符串存储到链表中,并将标号存储到加最后一位字符之前的字符串对应的结构体的code,更新字典。

4.main()函数主要是实现初始字典的构建,即’a’-’z’和’A’-’Z’的存储。

五、程序代码

子函数:

#ifndef DICTIONARY_H_INCLUDED

#define DICTIONARY_H_INCLUDED

void dictionary(SLNode *head,int x1,char c1[],int num)

{

    char c3[5];

    DataType C2;

    int  i;

    int flag=1,flag1=0,flag2=0,k=1;

    SLNode *p;

    printf("The message is:\n %s\n",c1);

    printf("The codeword is:\n");

    for(i=0;i<x1;i=i+flag2)

    {

        c3[0]=c1[i];

        c3[1]='\0';

        p=head;

        while(p->next!=NULL)

        {

            if(strcmp(c3,p->data.lable)) //c3与链表中的值不相等

            {

                p=p->next;

                flag1=0;

            }

            else //c3与链表中的值相等

            {

                c3[flag++]=c1[i+k];

                k++;

                c3[flag]='\0';

                flag2=flag-1;

                flag1=1;

                printf("%d  ",p->data.code);

                if(i+k>=x1) break;

                continue;

            }

        }

        if(flag1==0)  //插入新元素

        {

            strcpy(C2.lable,c3);

            C2.code=num++;

            ListInsert(head,ListLength(head),C2);

            flag=1;

            flag1=1;

            k=1;

            memset(c3,0,5);

        }

    }

    printf("\n");

    p=head;

    printf("The dictionary is:\n");

    while(p->next!=NULL)

    {

        printf("    %d  --  【%s】\n",p->next->data.code,p->next->data.lable);

        p=p->next;

    }

}

#endif // DICTIONARY_H_INCLUDED

主函数:

#include <stdio.h>

#include <stdlib.h>

#include <malloc.h>

#include <string.h>

typedef struct

{

    char lable[5];

    int code;

}DataType;

#include "list.h"

#include "dictionary.h"

int main()

{

    SLNode *head,*head1;

    DataType C2;

    int x1,x2,num=0;

    char c1[]="The Lempel Ziv algorithm can compress the English text by about fifty five percent.";

    char c2[]="The cat cannot sit on the canopy of the car.";

    char s1[]="\0",s2[]="\0";

    ListInitiate(&head);

    x1=strlen(c1);

    ListInitiate(&head1);

    x2=strlen(c2);

    for(s2[0]='A';s2[0]>='A'&&s2[0]<='Z';s2[0]++,num++)

    {

    strcpy(C2.lable,s2);

    C2.code=num;

    ListInsert(head,ListLength(head),C2);

    ListInsert(head1,ListLength(head1),C2);

    }

    for(s1[0]='a';s1[0]>='a'&&s1[0]<='z';s1[0]++,num++)

    {

    strcpy(C2.lable,s1);

    C2.code=num;

    ListInsert(head,ListLength(head),C2);

    ListInsert(head1,ListLength(head1),C2);

    }

    s1[0]='.';

    strcpy(C2.lable,s1);C2.code=num++;

    ListInsert(head,ListLength(head1),C2);

    dictionary(head,x1,c1,num);

    dictionary(head1,x2,c2,num);

    return 0;

}

六、程序运行结果

         

七、心得体会

这是上机实习的第一个程序,感觉要把学到的知识融会贯通运用到程序里,没有想象中的简单,光是刚开始想用什么样的数据类型存储字典就花费了好长的时间,第一节课并没有成功完成整个程序,但好在大体的概况已经出来了,课后又花了一点时间,终于编码成功。

实验二 计算信道容量

一、实验题目

1、已知:信源符号个数r、信宿符号个数s 、信道转移概率矩阵P。

2、输入:任意的一个信道转移概率矩阵。信源符号个数、信宿符号个数和每个具体的转移概率在运行时从键盘输入。

3、输出:信道容量C。

二、实验目的

1、理解和掌握信道容量的概念和物理意义;

2、理解计算离散信道容量的迭代算法。

三、算法设计

四、程序分析

1、信道容量:

2、当正向传输的信道容量和反向传输的信道容量在误差范围内时表示此时信道稳定,该信道容量即为所求。

3、计算正、反向传输的信道容量的迭代算法公式如下:

五、程序代码

/**********************************************************************************************

 【名称】:信道容量迭代法

 【函数】:计算a[i]函数、计算cap_result函数、计算cap_max函数、主函数

 【思路】:利用迭代法,使cap_result初步逼近cap_max,当误差小于e时,cap_result即为信道容量

**********************************************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

int X_num,Y_num;                      // X_num为信源个数,Y_num为信宿个数

int n=1;

double e;                       // 迭代法精度误差

double PXi[50];                 // 输入符号的概率P(xi)数组

double P[50][50];               // 信道转移概率矩阵

double a[50];

double cap_result;

double cap_max;

                // 迭代法参数a[i]、C、CC

double result;                     // 信道容量

/**************************************************************************

函数名:double Calculate_a(int k,double PXi[])

功能:计算并输出迭代法所需的参数a[k]

参数:

返回值:a[k],也就是P(yi|xj)*log(P(yi|xj)/P(yi))/log2对i从0到Y_num-1求和

**************************************************************************/

double Calculate_a(int k,double PXi[])

{

  int i,j;

  double sum1 = 0;

  for(j=0;j<Y_num;j++)

  {

         double sum = 0;                        // 必须在此处令sum置0

         for(i=0;i<X_num;i++)                   // 求和PXi[i] * P[i][j]得到P(yj)

         {

           sum += PXi[i] * P[i][j];//P[i][j]表示P(yj|xi);

         }

         sum1 += P[k][j] * log(P[k][j] / sum);  //求和得到a[k]

  }

  printf("a[%d] = %f\t",k,sum1);             // 输出a[k]

  return exp(sum1);

}

/**************************************************************************

函数名:double Calculate_cap_result(double PXi[],double a[])

功能:计算并输出迭代法所需的参数cap_result

参数:

返回值:cap_result,也即是用来逼近最值的参数

**************************************************************************/

double Calculate_cap_result(double PXi[],double a[])

{

  int i;

  double sum=0;

  for(i=0;i<X_num;i++)

  {

         sum += (PXi[i] * a[i]);

  }

  printf("较小值 =%f   \n",log(sum));             // 输出迭代法所需的参数cap_result

  return log(sum);

}

/**************************************************************************

函数名:double Calculate_cap_max(double a[])

功能:计算并输出迭代法所需的参数cap_max

参数:

返回值:cap_max,也即a[k]的最大值                                                              */

/**************************************************************************/

double Calculate_cap_max(double a[])

{

  int i;

  double max_a = a[0];

  for(i=0;i<X_num;i++)

  {

    if(a[i] > max_a)

         {

           max_a = a[i];

         }

  }

  printf("较大值 =%f",log(max_a));

  return log(max_a);

}

int main()

{

  int i,j,flag=1;

  printf("\n请输入信源个数X_num=  \n\t\t\t");

  scanf("%d",&X_num);

  printf("\n请输入信宿个数Y_num=  \n\t\t\t");

  scanf("%d",&Y_num);

  printf("\n请输入信道转移概率矩阵【P(Yj|Xi)】\n\n");

    for(i=0;i<X_num;i++)

      {

        for(j=0;j<Y_num;j++)

        {

            printf("P[%d][%d]=",i,j);

            scanf("%lf",&P[i][j]);

        }

      }

  printf("\n请输入迭代法精度误差(e):");

  scanf("%lf",&e);

  for(i=0;i<X_num;i++)

  PXi[i] = 1 / ((double)X_num);         // 初始化输入符号的概率P(xi),等概率预处理

  do

  {

    printf("\n第%d次迭代参数\n",n);

         for(i=0;i<X_num;i++)

      a[i] = Calculate_a(i,PXi);

      printf("\n");

      cap_result= Calculate_cap_result(PXi,a);

           cap_max= Calculate_cap_max(a);

           printf("\n");

         if(cap_max-cap_result>= e)                  // PXi[i]重新赋值

         {

      double sum = 0;

           for(i=0;i<X_num;i++)

           {

             sum += (PXi[i] * a[i]);

           }

           for(i=0;i<X_num;i++)

           {

             PXi[i] = ((PXi[i] * a[i]) / sum);

           }

           n ++;

         }

  }while(cap_max-cap_result>= e);

  printf("\n\n迭代次数为: %d\n" ,n);

  for(i=0;i<X_num;i++)

  {

    printf("最佳信源概率:%f\n" ,PXi[i]);

  }

  result = (cap_result/ log(2));

  printf("信道容量为:  %f\n\n",result);

  return 0;

}

六、程序运行结果

七、心得体会

在上机之前我对于老师讲解的信道容量的解释并不特别理解,至于在上机课上完全不知道如何设计程序算法,只能参照着老师PPT上的算法写程序;之后与同学进行了讨论,也把算法算了两遍,对信道容量的理解加深了一些,对算法流程也了解了些,虽然还是没有算出如算法所写的公式,但在计算过程中,对知识有了更深的理解。

实验三 汉明码编码与译码

一、实验题目

1、写一个错误生成器模块,在给定的一个比特流作输入时,它的输出流的每个比特流都以概率p发生了改变,即比特错误概率为p。

2、对m=3,将汉明码编码后的比特流输入到上述模块,然后对收到的字用译码器进行译码。

二、实验目的

1、理解和掌握汉明码编码与译码的原理;

三、算法设计

四、程序分析

1、错误生成模块:任一给以p,系统任意生成一数,若比p小则让其出错,否则不出错。

2、编码:首先随机生成H矩阵,由H矩阵生成G矩阵,利用C=mG编码。

3、解码:

  若v*H’=0,则没有出错,直接输出v中前k位;

  若v*H’!=0,列出所有的e和e*H’得到伴随阵s,若能在s中找到s=v*H

则c0=v-e,输出c0中前k位;若找不到s,则输出“错误位数大于纠错能力,无法解码”。

五、程序代码

#include <iostream>

#include <string>               // 字符串处理头文件

#include <iomanip>              // 输入输出控制头文件

#include <math.h>

#include <stdlib.h>

#include <time.h>

using namespace std;

void Err_Pro();

void Hamming_Decode();

int m,n,k,t,err,r,R[100],N[100],COUNT[100],num[100][100],Th[100][100],PT_S[100][100],PT_D[100][100];

int H[100][100],HT[100][100],Ig[100][100],P[100][100],G[100][100],Ibit[100],Cbit[100],Err_Cbit[100],V[100];            

/**************************************************************************/

/*函数名:void Binary_Conversion(int i)                                   */

/*功能:十-二进制转换                                                     */

/*说明:该函数输出二进制数为低位在前,高位在后                            */

/**************************************************************************/

void Binary_Conversion(int i)

{

  int j=0,temp=0;

  do                     // 生成完整n个二进制

  {

    temp = i % 2;        // 判断相应最低位为0或1(若为2的倍数则为0,否则为1)

         i = i / 2;           // 为考虑前一位为0或1做准备

         if(j < m)            // m确定二进制的位数

         {

           N[j] = temp;

           j++;

         }

  }while(i != 0);        // 等待i等于0(即等待十进制数为0时不进行二进制转换)

}

/**************************************************************************/

/*函数名:void Random_Array()                                             */

/*功能:将数组的列随机排放                                                */

/**************************************************************************/

void Random_Array()

{

  srand(unsigned(time(NULL)));   // 随机生成条件(抵消rand函数伪随机效果)

  cout << endl << "产生随机数为:" << endl;

  for(int j=0;j<n;j++)

  {

    loop:r= rand() % n;          // 随机生成范围为0~n-1的正整数

    for(int i=0;i<j;i++)

    {

      if(R[i] == r)       // 如果随机产生的数与已产生的数相等,则重新随机产生数

           {

        goto loop;

           }

    }

    R[j] = r;                    // 产生不重复的随机数

    cout << setw(4) << r + 1;

    for(int i=0;i<m;i++)

    {

      PT_D[i][j] = PT_S[i][r];   // 顺序转置系数矩阵->随机转置系数矩阵

         }

  }

}

/**************************************************************************/

/*函数名:void Creat_H()                                                  */

/*功能:创建系统型奇偶校验矩阵H                                          */

/*说明:系统型奇偶校验矩阵H由转置负系数矩阵和单位矩阵组成                */

/**************************************************************************/

void Creat_H()

{

  int i,j,count0=0,count1=0,count2=0,count3=0;

  /*************生成单位矩阵Ih************/ //教材P101

  for(i=0;i<m;i++)        //i表示行  j表示列

  {

         for(j=0;j<n;j++)

    {

           if((j >= k) && (i+k == j))

        Ih[i][j] = 1;

           else

        Ih[i][j] = 0;

         }

  }

  /*********生成转置负系数矩阵PT**********/

  for(i=0;i<m;i++)                // 转置二进制转换数组到PT_S

  {

    for(j=0;j<n;j++)

         {

           PT_S[i][j] = num[j][i];     // 生成顺序转置系数矩阵

         }

  }

  Random_Array();//将数组的列随机排放

  for(j=0;j<n;j++)

  {

    for(i=0;i<m;i++)

         {

           if(PT_D[i][j] == 0)

             count0 ++;

         }

         count1 = count0;              // count1记录每一列1的个数

         count0 = 0;

         if(count1 == (m-1))           // 将只有一位为1其余位为0的列的所有位置0

         {

           for(i=0;i<m;i++)

           {

                  PT_D[i][j] = 0;

           }

         }

         else

// COUNT数组记录只有一位为1其余位为0的列为0,其余位的值为PT_D列的位置值+1

             COUNT[count2] = j + 1;

             count2 ++;

  }

  for(int q=0;q<n;q++)            // 将PT_D的至少有两个1的列赋给PT

  {

    if(COUNT[q] > 0)

         {

           for(i=0;i<m;i++)

             PT[i][count3] = PT_D[i][q];

      count3 ++;

         }

  }

  cout << endl;

  /********生成系统型奇偶校验矩阵H********/

  for(i=0;i<m;i++)

  {

    for(j=0;j<n;j++)

         {

           H[i][j] = PT[i][j] + Ih[i][j];

         }

  }

  cout << endl << "系统型奇偶校验矩阵H为:" << endl;

  for(i=0;i<m;i++)              // 显示系统型奇偶校验矩阵H

  {

         for(j=0;j<n;j++)

    {

           cout << setw(2) << H[i][j] << setw(2);

         }

         cout << endl;

  }

}

/**************************************************************************/

/*函数名:void Creat_G()                                                  */

/*功能:创建系统型生成矩阵G                                               */

/*说明:系统型生成矩阵G由单位矩阵和系数矩阵组成                           */

/**************************************************************************/

void Creat_G()

{

  int i,j;

  /*************生成单位矩阵Ig************/

  for(i=0;i<k;i++)

  {

         for(j=0;j<n;j++)

    {

           if(i == j)

        Ig[i][j] = 1;

           else

        Ig[i][j] = 0;

         }

  }

  /*************生成系数矩阵P*************/

  for(j=0;j<n;j++)

  {

    for(i=0;i<k;i++)

         {

           if(j>k-1)

                  P[i][j] = PT[j-k][i];

         }

  }

  /**********生成系统型生成矩阵G**********/

  for(i=0;i<k;i++)

  {

         for(j=0;j<n;j++)

    {

      G[i][j] = P[i][j] + Ig[i][j];

         }

  }

  cout << endl << "系统型生成矩阵G为:" << endl;

  for(i=0;i<k;i++)              // 显示系统型奇偶校验矩阵H

  {

         for(j=0;j<n;j++)

    {

           cout << setw(2) << G[i][j] << setw(2);

         }

         cout << endl;

  }

}

/*******************************主函数*************************************/

int main()

{

  int i,j;

  cout << setw(30) << "汉明码" << endl;

  cout << "请输入校验元位数m = ";

  cin >> m;

  n = pow(2,m) - 1;     //码长

  k = pow(2,m) - 1 -m;  //信息源位数

  cout << "提示:" << setw(10) << "您输入的为(" <<n<< "," <<k<< ")汉明码,可纠正" << t << "个错误" << endl;

  cout << endl;

  for(i=0;i<n;i++)            // 将n个转换二进制数组存入二维数组

  {

    Binary_Conversion(i+1);

         for(j=0;j<m;j++)

         {

           num[i][j] = N[j];

           //num[i][m-j-1] = N[j];     // m-j-1意义在于将二进制高位在前,低位在后

         }

  }

  cout << "n个二进制转换表为:" << endl;

  for(i=0;i<n;i++)              // 输出二进制转换对应表  低位在前高位在后

  {

         for(j=0;j<m;j++)

         {

      cout << num[i][j] << setw(2);

         }

    cout << setw(4);

  }

  cout << endl;

  Creat_H();

  Creat_G();

  cout << endl << "请输入" << k << "位信息比特流:" << endl;

  for(i=0;i<k;i++)

           cin >> Ibit[i];

  for(i=0;i<n;i++)

  {

         for(j=0;j<k;j++)

         {

      Cbit[i] += (Ibit[j] * G[j][i]);       // 十进制加法

           Cbit[i] = Cbit[i] % 2;                // 将十进制转换二进制

         }

  }

  cout << endl << "输出" << n << "位码字比特流:" << endl;

  for(i=0;i<n;i++)                       //输出编码后的码字

         cout << setw(3) << Cbit[i];

  cout << endl;

  Err_Pro();         //错误概率函数

  Hamming_Decode();   //汉明译码

  return 0;

}

/**************************************************************************/

/*函数名:void Err_Pro()                                                  */

/*功能:产生错误概率函数                                                  */

/**************************************************************************/

void Err_Pro()

{

  float p;

    cout << endl << "请输入错误概率p = ";

  cin >> p;

  for(int x=0;x<n;x++)

  {

    if((float)((rand() % 1001) * 0.001) < p) // 如果小于概率,则原码0与1互换

         {

           err ++;

      Err_Cbit[x] = (Cbit[x] + 1) % 2;

         }

         else

           Err_Cbit[x] = Cbit[x];                  // 如果大于错误概率,则赋值原码

  }

  cout << endl << "输出" << n << "位码字比特流(每位等概出错):" << endl;

  for(int y=0;y<n;y++)

         cout << setw(3) << Err_Cbit[y];

  cout << endl;

}

/**************************************************************************/

/*函数名:void Hamming_Decode()                                           */

/*功能:汉明译码函数                                                  */

/**************************************************************************/

void Hamming_Decode()

{

  int i,j,flag=0,d;

  for(i=0;i<n;i++)                  // 得到H的转置矩阵HT

  {

    for(j=0;j<m;j++)

         {

           HT[i][j] = H[j][i];

         }

  }

    cout << endl << "输出转置奇偶校验矩阵HT为:" << endl;

  for(i=0;i<n;i++)

  {

    for(j=0;j<m;j++)

         {

           cout << setw(3) << HT[i][j] << setw(3);

         }

         cout << endl;

  }

  for(i=0;i<m;i++)                      // 计算伴随矩阵

  {

    for(j=0;j<n;j++)

    {

      V[i] += Err_Cbit[j] * HT[j][i];

    }

         if(V[i] % 2 == 0)                   // 将十进制转换二进制

           V[i] = 0;

         else

           V[i] = 1;

  }

  cout << endl << "输出伴随矩阵为:" << endl;

  for(i=0;i<m;i++)

    cout << V[i] << setw(2);

  cout << endl;

  for(i=0;i<m;i++)

  {

    if(V[i] == 0)                // 如果伴随矩阵为零矩阵,则直接输出原码流

         {

      if(i == m-1)

           {

             cout << endl << "<译码正确!>输出码流为:" << endl;

             for(j=0;j<n;j++)

          cout << Err_Cbit[j] << setw(3);

        cout << endl;

           }

         }

         else

         {

           flag ++;             // 如果伴随矩阵为非零矩阵,则标志位自加1

           break;

         }

  }

  if(flag != 0)

  {

    if(err == 1)                         // 伴随矩阵为非零矩阵时执行

         {

           for(i=0;i<n;i++)

           {

             for(j=0;j<m;j++)

                  {

          if(V[j] == HT[i][j])

                    {

                      if(j == (m-1)) d = i;//d记录行

                    }

                    else

                      break;

                  }

           }

           cout << endl << "<译码正确!>输出码流为:"<< endl;

      Err_Cbit[d] = (Err_Cbit[d] + 1) % 2;

           for(i=0;i<n;i++)

        cout << setw(3) << Err_Cbit[i] << setw(3);

           cout << endl;

         }

         else

           cout << endl << "由于本次编码有" << err << "个错误位,大于纠错能力" << t << ",故<译码错误!>" << endl;

  }

 }

六、程序运行结果

七、心得体会

经过对程序的理解和掌握,我更加清楚的掌握了汉明编码与译码的方法,这是我感觉收获最大的地方。对伴随式也有了比较深刻的理解,之后做题目和看书对这块的知识也有了更透彻的理解,掌握也更加轻松一些。

实验四 求循环码的最小汉明距离

一、实验题目

1、输入码的生成多项式;

2、输出码的最小汉明距离。

二、实验目的

1、理解和掌握循环码的概念以及生成方法;

2、求出循环码的最小距离。

三、算法设计

四、程序分析

1.采用Matlab编程;

2.cyclpoly(15, 4,'all')函数用来产生(15,4)循环码的所有生成多项式;

3.circshift()函数是进行移位操作函数;

4.sym2poly()函数是将多项式转化为矩阵表示形式;

5.expand(x^r*m)函数是对m进行左移r位的操作;

五、程序代码

syms x ;

G=cyclpoly(15, 4,'all');%求出所有的生成多项式 功能:产生循环码的生成多项式

g=G(2,:);%选择所有生成多项式中的第二个作为(15,4)循环码的生成多项式

r=15-4 ;          %监督位数

m=x^3+x^2+1;     %信息码元

m1=expand(x^r*m); %用x^r乘以m,相当于对m进行左移r位的操作

m2=sym2poly(m1);  %将多项式转化为矩阵表示形式

[Q,R] = DECONV(m2,g); %求m2除以g所得的余数

%由于在求解余数时是按照一般的算术运算计算的,

%而实际要求的为模2运算,转化为模2运算

R=abs(R);

for i=1:length(R)

       R(i)=mod( R(i),2);

end  

%C(X)=x^r*m(x)+x^r*m(x)/g(x)

T=R+m2 ;%T为生成的一个循环码字

T2(1,:)=T;

[W,L]=size(T);

%将T2循环移位,得到其他的码字

for i=1:L-1

    T2(i+1,:)=circshift(T2(i,:),[0,1]);

end  

Y=[zeros(1,L);T2]; %Y矩阵为生成的全部码字

%求最小汉明距离

t=1;

 for i=1:15

    for j=i+1:16

       M(t,:)=(Y(i,:)~=Y(j,:));

       t=t+1;

   end

end                   %分别比较两行中不同的元素

S=(sum(M,2))';        %将M矩阵的每一行求和,得出任意两个码字之间的距离

d=min(S);             %最小汉明距离

display(d);

六、程序运行结果

七、心得体会

刚刚接触Matlab不久,对于Matlab里的函数不是十分了解,在解读程序时需要将函数一个个打开,解读它的注释,了解函数的算法;经过对程序细致的解读,不但对求循环码的最小汉明距离有了更深的了解,对Matlab的软件也有了更多的掌握,可谓收获颇丰。只是可惜的是自己的编程能力不好,时间不允许我慢慢磨蹭着自己写程序,所以只好看成熟的程序,看会了、了解了,这些知识也是我的。

实验五 维特比译码

一、实验题目

写一个维特比译码器软件,它接受下列输入:

1、以八进制形式给出的码的参数,以及

2、接收到的比特流。

二、实验目的

1、理解和掌握卷积码的概念;

2、掌握维特比译码的方法;

三、算法设计

四、程序分析

min_dist(a,b)函数计算两个码字的汉明重量;

num_jinzhi(num,jinzhi,wei)函数将十进制的 num转换为进制为jinzhi的wei位数;

init_state()函数是对state[ ]

矩阵进行初始化操作;

G矩阵存储码的参数的二进制形式;

xinxi[ ]矩阵存储输入比特流;

state[ ]矩阵存储如下表的状态;

五、程序代码

主函数:

display('编码序列:');

xinxi=[1 0 1 0 0 1 1 0 1]

% in=0;

input_g= '75';

str_length=length(input_g);

%-----------将输入的char型数字转换成二进制数------------------------%

for i=1:str_length

    g_dec=base2dec(input_g,8);%将'75'这个8进制数转换成10进制

    g=num_jinzhi(g_dec,2,3*str_length);%将10进制数转换成2进制

end

 g;      %测试g

global G;

for i=1:str_length

    G_yuanshi(i,1:3)=g(3*i-2:3*i);%将得到的二进制数  每三个分成一行

end

G=G_yuanshi';

% ------------------------生成查询表格-----------------------------%

state=init_state;

% ---------------------以下为编码算法------------------------------ %

xinxi_bu0=[xinxi 0 0];

xinxi_length=length(xinxi_bu0); %这里的长度实际为补0后的长度

state_temp=[0 0];               %初始的状态寄存器里面为00

for i=1:xinxi_length

    for j=1:4 %对应四种状态

        if isequal(state_temp,state{j,1})

            if xinxi_bu0(i)==0  %若输入为0

                code(2*i-1:2*i)=state{j,3};%输出码字

                state_temp=state{j,4}; %下一状态

            else if xinxi_bu0(i)==1 %若输入为1

                code(2*i-1:2*i)=state{j,6};%输出码字

                state_temp=state{j,7}; %下一状态

                end

            end

            break;

        end

    end

end

display('信息编码如下:');

code

%---------------加入错误编码 (这里仅将第三位出错)---------------------- %

code(3)=~code(3);

display('出错后的编码:');

code

%---------------------以下为解码算法--------------------------------- %

code_length=length(code);  %这里的长度实际为补0后的长度

state_temp=[0 0];          %初始的状态寄存器里面为00

%计算最初始两个码字 四条路径的汉明距离

state{1,10}=min_dist(state{1,3},[code(1) code(2)])+min_dist(state{1,3},[code(3) code(4)]);%第一条路径的汉明距离

state{2,10}=min_dist(state{1,3},[code(1) code(2)])+min_dist(state{1,6},[code(3) code(4)]);%第二条路径的汉明距离

state{3,10}=min_dist(state{1,6},[code(1) code(2)])+min_dist(state{2,3},[code(3) code(4)]);%第三条路径的汉明距离

state{4,10}=min_dist(state{1,6},[code(1) code(2)])+min_dist(state{2,6},[code(3) code(4)]);%第四条路径的汉明距离

state{1,11}=[0 0];%存放第一条路径的前两个码字

state{2,11}=[0 1];%存放第二条路径的前两个码字

state{3,11}=[1 0];%存放第三条路径的前两个码字

state{4,11}=[1 1];%存放第四条路径的前两个码字

for i=1:4

    state{i,12}=state{i,11};

end

% for i=3:code_length/2;

i=3;

while i<=code_length/2

    temp=[code(2*i-1) code(2*i)]; %下一个码字(2位)

%------------四种状态分别输入0/1后得到八种状态,每种可能的距离-----------%

    for j=1:4

        state{j,8}=min_dist(temp,state{j,3});%输入0的可能最小距离

        state{j,9}=min_dist(temp,state{j,6});%输入1的可能最小距离

    end

   

%--------------------------每种状态所对应的下一编码---------------------%

    if (state{1,8}+state{1,10})<(state{3,8}+state{3,10}) %第一个状态点的路径选取

         state{1,12}=[state{1,11} 0];%获得下一个解码

    else state{1,12}=[state{3,11} 0];

    end

   

    if (state{1,9}+state{1,10})<(state{3,9}+state{3,10})%第二个状态点的路径选取

        state{2,12}=[state{1,11} 1];

    else state{2,12}=[state{3,11} 1];

    end

   

    if (state{2,8}+state{2,10})<(state{4,8}+state{4,10})%第三个状态点的路径选取

        state{3,12}=[state{2,11} 0];

    else state{3,12}=[state{4,11} 0];

    end

   

    if (state{2,9}+state{2,10})<(state{4,9}+state{4,10})%第四个状态点的路径选取

        state{4,12}=[state{2,11} 1];

    else state{4,12}=[state{4,11} 1];

    end

    %-------------state{:,13}用来临时存放每条路径的汉明重---------------%

    state{1,13}=min((state{1,8}+state{1,10}),(state{3,8}+state{3,10}));%第一个状态点在取汉明重量较小的那条路径

    state{2,13}=min((state{1,9}+state{1,10}),(state{3,9}+state{3,10}));%第二个状态点在取汉明重量较小的那条路径

    state{3,13}=min((state{2,8}+state{2,10}),(state{4,8}+state{4,10}));%第三个状态点在取汉明重量较小的那条路径

    state{4,13}=min((state{2,9}+state{2,10}),(state{4,9}+state{4,10}));%第四个状态点在取汉明重量较小的那条路径

   

    i=i+1;

    for j=1:4

        state{j,10}=state{j,13};%更新state{:,10}

        state{j,11}=state{j,12};%更新state{:,11}

    end

end

%-----------------------判断四组码中的最小距---------------------------%

dis_temp=[state{1,10} state{2,10} state{3,10} state{4,10}];

index=find(min(dis_temp) == dis_temp);

if length(index)>1  %有多条最小路径时的处理方式

    index=index(1);

end

decode_length=length(state{index,12});

display('解码如下:')

decode=state{index,12}(1:decode_length-2)   %%去掉最后面的两个0

%-------------------测试解码和原码是否完全相同------------------------%

for i=1:decode_length-2

    test(i)=decode(i) - xinxi(i);

end

 display('检测解码是否正确码字如下'); test

子函数:

%----------------将十进制的 num转换为进制为jinzhi的wei位数--------------%

function out=num_jinzhi(num,jinzhi,wei)

% yushu=zeros(1,wei);%为了提高计算速度,提前申请输出数据的内存

i=1;

shang_pre=num;

shang_back=num;

while shang_back>=jinzhi

    yushu(i)=mod(shang_pre,jinzhi);%将10进制数变成二进制数

    i=i+1;

    shang_back=fix(shang_pre/jinzhi);

    shang_pre=shang_back;

end

yushu(i)=shang_back;

for i=1:wei

    out_yushu(i)=yushu(wei-i+1);%将转换后的结果调整  高位在前,低位在后

end

out=out_yushu;

function out=init_state()

global G;

state=cell(4,7);  %创建4*7的数组 可以存储不同类型的数据

state(:)={[0]};

state{1,1}=[0 0];%见教材P164  生成初始状态

state{2,1}=[1 0];

state{3,1}=[0 1];

state{4,1}=[1 1];

for i=1:4

    state{i,2}=0;

    in=0;

    % % % 输入0

    temp=[in state{i,1}];

    state{i,3}=mod(temp*G,2); %输出值

    state{i,4}=[in state{i,1}(1)];%下一状态

    % % % 输入1

    in=1;

    state{i,5}=1;

    temp=[in state{i,1}];

    state{i,6}=mod(temp*G,2); %输出值

    state{i,7}=[in state{i,1}(1)];%下一状态

end

out=state;

%--------------------------求两个码字的汉明重量------------------------%

function out=min_dist(a,b)

min_length=length(a);

cnt=0;

for i=1:min_length

    if a(i)~=b(i);

        cnt=cnt+1;

    end

end

out=cnt;

六、程序运行结果

七、心得体会

维特比译码在学习上比较轻松,理解起来也比较容易,但程序的编写就比较复杂一点,再加上用Matlab编程,对我而言难度就增加了;但是将主要流程理解清楚后,搞懂主要变量的变化之后,程序也就变得清晰了;理解了这个程序,让我对Matlab编程的掌握进一步加深了,希望以后能够自己独立编写程序。

更多相关推荐:
上机实习报告

上机实习报告实习时间20xx61720xx620学校中原工学院学院电信学院专业测控技术与仪器学生学号20xx00454204学生姓名张旭前言计算机在当今社会起到越来越重要的地位计算机网络是一门具有实用性的的信息...

计算机实训总报告

HEFEIUNIVERSITY计算机实训综合报告系别电子信息与电气工程系专业通信工程班级通信工程2班学号姓名指导老师完成时间20xx12311绪论一个学期的计算机实训课已经结束了通过方老师一次又一次的讲解我们的...

计算机上机实验报告模板

交通与汽车工程学院实验报告课程名称课程代码学院直属系交通与汽车工程学院年级专业班学生姓名学号实验总成绩任课教师开课学院交通与汽车工程学院实验中心名称汽车交通实验中心西华大学实验报告西华大学实验报告理工类开课学院...

中级财务会计模拟实训实习报告

为了适应高等职业教育的需要我们以会计法税法企业会计准则企业会计制度中级财务会计等为依据在总结财务会计实训教学成功经验的基础上以企业真实情况为基础以典型经济业务为主线设计了企业在一个会计核算期间所发生的各种经济业...

上 机 实 习 报 告

南通大学管理学院一、实习目的要求1、掌握“中国知网”的整体结构;2、学会利用关键词检索相应的期刊论文,并对这些期刊论文的主题标引(关键词)对照教材的标引规则作出评价;3、字体、字号要求:汉字一律用5号宋体字;西…

CAD上机实习报告

CAD班级:电子质检1101班姓名:郭利智学号:20xx110902指导老师:潘庆杰上机实习报告1.实习任务用一周的时间对AUTOCAD软件练习的同时,完成机自教研室发的二维图例以及6个练习图,并完成相应的实习…

AutoCAD上机实习报告

AutoCAD上机实习报告学院电子信息学院专业测控技术与仪器班级测控122班姓名李兴兴学号20xx00454222AutoCAD上机实习报告一实习目的本次CAD上机实习是为了利用计算机绘图软件autoCAD进行...

vs20xx 计算机上机考试系统实训报告

第二部分实训指导内容提要本部分包含基础实训和课程设计涵盖了具体任务基础实训学生报告范例课程设计学生报告范例C程序设计项目实训设计指导书一项目实训的目的C程序设计项目实训是在学习C程序设计理论课的基础上进行的一个...

数据结构上机实习报告

数据结构上机实习报告实验题目一元多项式班级19xx21姓名邹冠宏完成日期20xx930一问题分析1问题描述设计一个n元多项式程序并完成多项式的加法乘法运算从实际的角度出发这里设计的程序是基于一元n次多项式的数学...

空间数据结构上机实习报告

空间数据结构测绘08级上机报告姓名班级学号07082967时间20xx年1月得分环境与测绘学院上机练习2顺序表的定义与应用实验目的熟练掌握顺序表的定义与应用通过上机实践加深对顺序表概念的理解训练学生利用顺序表来...

施工组织管理上机实习报告

重庆交通大学学生实验报告实验课程名称施工组织设计开课实验室工程模拟实验室学院年级专业班工管2班学生姓名号开课时间20xx至20xx学年第2学期一实验目的通过上机实验掌握项目管理软件在施工管理中的应用了解软件的基...

SIMTRADE上机实习报告

国际经济与贸易专业实习报告书一实习时间二实习地点三实习对象SimTrade外贸实习平台外贸实习平台归纳总结了整个外贸行业的流程和惯例在互联网上建立几近真实的国际贸易虚拟环境让学生在其中亲身体验国际贸易的风险和乐...

上机实习报告(25篇)