1. 要求
设计一套信道编码系统,实现以下功能:
- 通过输入生成矩阵,系统给出一般线性分组编码集
- 通过设定n,k的值,系统构造出二元(n,k)汉明码的校验矩阵和生成矩阵
- 通过输入的循环码多项式以及码长,系统能够给出相应的循环码码集
- 给出上述要求的具体实现过程并且对结果进行验证
2. 过程
1.实验包含三种不同的编码,考虑到三种编码用户输入的初始条件都不相同,所以设计三个单独的模块,通过主菜单联合,菜单设计如下:
图1 菜单
2.一般线性分组码需要输入生成矩阵。通过RichTextBox控件实现,其界面如下:
图2 一般线性分组码
构造按钮中代码如下:
private void button1_Click(object sender, EventArgs e)
{
int a = richTextBox1.Lines.Length;
char[] sp = new char[3] { ' ', '\t', '\n' };
string[] str1 = new string[100];
str1 = richTextBox1.Text.Split(sp);
int nn = Convert.ToInt32(Math.Pow(2, a));//信息个数
string[] xx=new string[nn];
int b = str1.Length / a;
double[,] jz = new double[a, b];
label3.Text="码字:\n";
label4.Text = "信息:\n";
string s="";
for (int i = 0; i < a; i++)
{
for (int j = 0; j < b; j++)
{
jz[i, j] = Convert.ToDouble(str1[i * b + j]);
}
}
for (int k = 0; k < nn ; k++)
{
xx[k] = Convert.ToString(k, 2).PadLeft(a, '0');
string ss = xx[k];//信息
int mm = 0;
for (int i = 0; i < a; i++)
{
s = "";
for (int j = 0; j < b; j++)
{
s += Convert.ToString(jz[i, j]);
}
mm ^= Convert.ToInt32(Convert.ToString(ss[i])) * Convert.ToInt32(s, 2);//异或计算得到信息对应的码字的十进制数
}
label3.Text += ss + '\n';
label4.Text += Convert.ToString(mm, 2).PadLeft(b,'0') + "\n";
}
}
3.汉明码设计我通过TextBox控件实现n,k值的输入,其设计界面如下:
图3 汉明码
构造按钮中代码如下:
private void button1_Click(object sender, EventArgs e)
{
int n = Convert.ToInt32(textBox1.Text);
int k = Convert.ToInt32(textBox2.Text);
string[] H = new string[n];//校验矩阵
string[] G = new string[n];//生成矩阵
label4.Text="";
label5.Text = "";
for (int i = 0; i < n; i++)
{
H[i] = "0";//初始化校验矩阵
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - k; j++)
{
if (i + 1 == Math.Pow(2, j))//判断是否为单位矩阵中的某一列
{
H[n-1-j] = Convert.ToString(i + 1, 2).PadLeft(n - k, '0');//加入校验矩阵中对应的位置
H[i] = Convert.ToString(n - j, 2).PadLeft(n - k, '0');//校验矩阵当前位置加入2的n-j次方对应的二进制数
break;
}
else
{
if (H[i]=="0")//判断是否已经加入过值
{ H[i] = Convert.ToString(i + 1, 2).PadLeft(n - k, '0'); }
}
}
}
for (int i = 0; i < n - k; i++)
{
for (int j = 0; j < n; j++)
{
label4.Text += H[j][i];
}
label4.Text += '\n';
}
for (int i = 0; i < n; i++)
{
if (i < k)//生成矩阵前k列为单位矩阵
{
int r = Convert.ToInt32(Math.Pow(2, k - i - 1));
G[i] = Convert.ToString(r, 2).PadLeft(k, '0');
}
else
{
for (int j = 0; j < k; j++)
{
G[i] += H[j][i-k];//校验矩阵前k列转置
}
}
}
for (int i = 0; i < k; i++)
{
for (int j = 0; j < n; j++)
{
label5.Text += G[j][i];
}
label5.Text += '\n';
}
}
4.循环码通过TextBox控件获取生成多项式的系数以及码长,其界面设计如下:
图4 循环码
其中构造按钮代码如下:
private void button1_Click(object sender, EventArgs e)
{
string s = textBox1.Text;//生成多项式系数
int n = Convert.ToInt32(textBox2.Text);//码长
int k = n - s.Length + 1;
string[] G = new string[k];//生成矩阵
int nn=Convert.ToInt32(Math.Pow(2,k));//信息数量
string[] m = new string[nn];//信息矢量
s = s.PadLeft(n, '0');//n位二进制数
G[k-1]=s;
label2.Text = "信息矢量:\n";
label3.Text = "码矢:\n";
for(int i=k-2;i>=0;i--)//移位过程
{
s+="0";
G[i]=s.Substring(s.Length-n);
}
for (int q = 0; q < nn ; q++)
{
m[q] = Convert.ToString(q, 2).PadLeft(k, '0');
string ss = m[q];
int mm = 0;
for (int i = 0; i < k; i++)
{
mm ^= Convert.ToInt32(Convert.ToString(ss[i])) * Convert.ToInt32(G[i], 2);//异或得出码矢的十进制
}
label2.Text += ss + '\n';
label3.Text += Convert.ToString(mm, 2).PadLeft(n,'0') + "\n";
}
}
经过上述设计,系统已经构造完成
3. 测试
1.测试一般线性分组编码:
图5 一般线性分组码测试1
图6 一般线性分组码测试2
以上分别为(6,3)线性分组码和(7,4)线性分组码,通过验证,以上结果均正确
2.接下来开始测试汉明码(汉明码集数量较大,因此只需给出校验矩阵和生成矩阵即可):
图7 汉明码测试1
图8 汉明码测试2
测试2中结果异常,后发现汉明码的n和k值服从(n,k)=(2^m-1,2^m-1-m),其中m=n-k
所以想要生成m=4的汉明码,需要选择(15,11)汉明码,测试如下:
图9 汉明码测试3
结果正确
3.循环码测试
图10 循环码测试1,(7,3)循环码
图11 循环码测试2,(7,4)循环码
验证结果均正确
4. 总结
本文介绍了一般线性分组码、汉明码、循环码的详细编码过程,可以看出决定其编码结果的关键属性就是它们的生成矩阵,一般线性分组码的模块实际上就是直接将给定的生成矩阵来转换成码集,而汉明码和循环码的模块中,其最大的一个任务点就是根据他们相应的特性来得到生成矩阵然后通过一般线性分组码的模块功能实现编码。可以先去研究其中的规律和相关性质然后才开始编写代码,例如在汉明码的编程中,汉明码的校验矩阵有特殊的性质,校验矩阵的列数刚好等于二进制时n-k个码元所能组成的列矢量总数(除去0矢量),所以只需将列进行置换就可以得到校验矩阵,这给编程带来了极大的简便。实验中也有很多不足,例如编码结果没有调整为系统码,而且没有加入一个检验功能,通过校验矩阵来检验是否为码字,最后在循环码系统中不能够直接进行因式分解得出生成多项式,所以程序还有很多需要改进的地方。