《信息论》课程设计
成绩:2016-2017 学年第 1 学期 《信息论》课程设计 学院名称:班级学号:学生姓名:教师姓名:2016 年 12 月 一、判定唯一可译码 1. 任务说明输入:任意的一个码(即已知码字个数及每个具体的码字)输出:判决结果(是/不是)输入文件:in1.txt,含至少 2 组码,每组的结尾为”$”符输出文件:out1.txt,对每组码的判断结果说明:为了简化设计,可以假定码字为 0,1 串 2. 实现原理判断方法:将码 C 中所有码字可能的尾随后缀组成一个集合 F,当且仅当集合 F 中没有包含任一码字,则可判断此码 C 为唯一可译变长码。构成集合 F:首先观察码 C 中最短的码字是否是其他码字的前缀。若是,将其所有可能的尾随后缀排列出。就是将其他码字序列中截去与其最短码字相同的前缀部分,将余下的序列为尾随后缀。而这些尾随后缀又可能是某些码字的前缀,或者最短码字又仍是这些尾随后缀的前缀,再将由这些尾随后缀产生的新的尾随后缀列出。然后再观察这些新的尾随后缀是否是某些码字的前缀,或观察有否其他码字是这些新的尾随后缀的前缀,再将产生的尾随后缀列出,依次下去,直至没有一个尾随后缀是码字的前缀或没有新的尾随后缀产生为止。
1)首先好后缀算法与kmp完全不同,kmp是寻找最长的公共前缀和后缀,而好后缀suff[i]是求pattern中以i位置字符为后缀和以最后一个字符为后缀的公共后缀串的长度,完全不一样2)和3)我在原博...。无穷大的值被格式化为一个字符串,通常具有单个字符 \u221e,具有正数或负数前缀和后缀。无穷大的值被格式化为单个字符,通常是\u221e,具有正数或负数前缀和后缀。
\n";}else{for (i = a[z]; i<N - 1; i++)/*将原始码字生成的尾随后缀集合 s[1]放入 f中*/{for (j = i + 1; j<N; j++){patterson(c[i], c[j]);}}for (i = 0;; i++)//根据原始码与 s[i]生成 s[i+1]也放入 f[i]{int s = 0;for (j = a[z]; j<N; j++)/*判断 s[i+1]中的字符串是否与 s[i]中一样 ,重复的则不再添加*/{if (i == sum){s = 1; break;}elsepatterson(f[i], c[j]);}if (s == 1)break;}for (i = 0; i<sum; i++)/*判断尾随后缀与原始码字是否相同,相同则不是唯一可译码*/{for (j = a[z]; j<N; j++){if (strcmp(f[i], c[j]) == 0){flag = 1;break;}}}if (flag == 1){for (int y = a[z]; y < N; y++)file1 << c[y] << ' ';file1 << "不是唯一可译码。
\n";}else{for (int y = a[z]; y < N; y++)file1 << c[y] << ' ';file1 << "是唯一可译码。\n";}}file1 << "尾随后缀集合为:";for (i = 0; i < sum; i++)file1 << f[i] << ' ';file1 << "\n";z++;sum = 0;}}4. 说码结为例 结出判结果则能正确5. 通的过写,二个过修计,较为 运行结 果说明:输入文结束以“$”符例,多组码判结果分析:程判断结果,在果,不能完全能说明程序的确,则可验证设计体 会通过此实验的过程中出现两选取两个字个难点是码字修改,改为单关键部分调为简单,实现果 文件中第一个符号结尾;“判断同上。 程序首先读取第二行输出该全说明程序的的正确性,由于证此程序的正会 的设计,进一两大难点,第字符数组保存码字的文件读取个字符读取能用尾随后缀生现时注意细节个数字表示码“$”符号后的输取第一组码,该码字产生的正确性,可于选取的两组正确性,即可一步加深了我一点就是,作码字和后缀,取,起初考虑的能简化程序的生成函数即可节、没有逻辑输入文件:in1.tx码的组数,第的数字表示下输出文件:out1.t进行是否唯的尾随后缀集能存在偶然性组数据来自课用于判断码是我对唯一可译作为此程序的,通过码字长的是整个码字的设计。
误码率计算困难香农采取的方法:用随机编码方法得到所有可能码的集合,在其中随机选择一个码作为信道码,利用联合典型序列译码,利用大数定理计算在集合平均意义上的该码性能2.2 证明从早期的粗糙定性证明到后来给定精确差错概率指数上下限的严格数学证明。例如表6.2 (d)的编码方案,字符a 的编码01 是字符b 的编码010 的前缀部分,这样对于代码串0101001,既是aac 的代码,也是abd 和bda 的代码,因此,这样的编码不能保证译码的唯一性,我们称之为具有二义性的译码。 第4章信道编码k比特块 mk信息比特 n , k 分组 编码输出 1 复用 系统编码器 m n -k 校验比特块 1 长度n=mk n , k 分组 2 块交织器 系统编码器 m n -k 2 校验比特块 图4-14 并行级联分组码编码方框图 第4章信道编码4.6.2 串行与并行的级联卷积码 1. turbo码 带交织的并行级联卷积码pccc parallelly concatenatedconvolutional codes 也叫turbo码,turbo编码器的基本结构如图4-15所示, 它由两个并联的递归系统卷积码rsc recursivesystematic convolutional )编码器组成,并在第二个编码器前面串接了一个交织器。
哈夫曼编码是一种可变长的编码,它依据字符出现的概率来决定字符编码的长度,使得出现概率大的字符编码长度短,出现概率小的字符的编码长度长,于是可以减少整体的编码的长度。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。4.译码的思想是循环读入一串哈夫曼序列,读到“0”从根结点的左孩子继续读,读到“1”从右孩子继续,如果读到一个结点的左孩子和右孩子是否都为0,如果是说明已经读到了一个叶子(字符),翻译一个字符成功,把该叶子结点代表的字符存在一个存储翻译字符的数组中,然后继续从根结点开始读,直到读完这串哈夫曼序列,遇到结束符便退出翻译循环。
同其他码词长度可变的编码一样,如果码串中没有错误,可区别的不同码词的生成是基于不同符号出现的不同概率.20, p(d)=0.13。2.哈夫曼编码规定哈夫曼编码的左分支代表0,右分支代表1,则从根节点到每个叶子结点所经过的路径组成的0和1的序列便为该叶子结点对应字符的编码,称为哈夫曼编码。为使不等长编码为前缀编码(即要求一个字符的编码不能是另一个字符编码的前缀),可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值。
完成子和父亲指针权重最小的两将两个字符的从筛选列表中再对文件内容果 对 n 个符号曼编码,得到游结果,再进行游会 相对简单,首先再使用霍夫夫曼码的编码短码;二是缩成哈夫曼的编针,之后对所有两个字符,将的权重之和赋中淘汰掉。依容进行编码。输序列进行游程游程编码结果游程译码,得先计算每次连曼编码。霍夫码方法保证了缩减信源的最编码首先建立有字符根据权将这两个字符赋值给新节点次对列表中剩 输入文件:in2.tx输出文件:out2.t程编码后输出果的霍夫曼码得到原符号序连续相同字符夫曼编码用概了概率大的符最后两个码字立哈夫曼树,权重进行编码分别作为新节,将新二叉树剩下的字符进xt txt 出“0”游程码。然后进行序列。第二组符符的个数,然概率匹配方法符号对应于短字总是最后一定义当前节码(先在所有节点的左子和树放入筛选字进行权重最小长度和“1”行译码,首先的符号序列编码然后将每次连法进行信源编短码,概率小一位不同,从节点的字符,当有可能出现的和右子建立一字符中,再将小的筛选,直游程长度,的是霍夫曼译码译码过程相连续相同的字编码,有两个小的符号对应从而保证霍夫当前节点的左的字符中筛选一个小的二叉将筛选过的两直到根节点) 再对译码,相同。
字符及个明显应于长夫曼编左子、选出当叉树,两个字,最三、算术编码的编码与译码 1. 任务说明 要求:输入字符集为{a,b},且 p(a)=1/4,p(2)=3/4.对长度 L<=30 的序列进行算术编码,并进反向译码 输入文件:in3.txt,含至少两组输入,每组为满足要求的串 输出文件:out3.txt,对每组输入的编码和译码结果 2. 实现原理 算术编码用到两个基本的参数:符号的概率和它的编码间隔。信源符号的概率决定压缩编码的效率,也决定编码过程中信源符号的间隔,而这些间隔包含在 0 到 1 之间。编码过程中的间隔决定了符号压缩后的输出。 给定事件序列的算术编码步骤如下: (1)编码器在开始时将“当前间隔” [ L, H) 设置为[0,1)。 (2)对每一事件,编码器按步骤(a)和(b)进行处理(a)编码器将“当前间隔”分为子间隔,每一个事件一个。(b)一个子间隔的大小与下一个将出现的事件的概率成比例,编码器选择子间隔对应于下一个确切发生的事件相对应,并使它成为新的“当前间隔”。 (3)最后输出的“当前间隔”的下边界就是该给定事件序列的算术编码。
众所周知,在计算机当中,数据的存储和加工都是以字节作为基本单位的,一个西文字符要通过一个字节来表达,而一个汉字就要用两个字节,我们把这种每一个字符都通过相同的字节数来表达的编码形式称为定长编码.以西文为例,例如我们要在计算机当中存储这样的一句话:i am a teacher.就需要15个字节,也就是120个二进制位的数据来实现.与这种定长编码不同的是,哈夫曼编码是一种变长编码.它根据字符出现的概率来构造平均长度最短的编码.换句话说如果一个字符在一段文档当中出现的次数多,它的编码就相应的短,如果一个字符在一段文档当中出现的次数少,它的编码就相应的长.当编码中,各码字的长度严格按照对应符号出现的概率大小进行逆序排列时,则编码的平均长度是最小的.这就是哈夫曼编码实现数据压缩的基本原理.要想得到一段数据的哈夫曼编码,需要用到三个步骤:第一步:扫描需编码的数据,统计原数据中各字符出现的概率.第二步:利用得到的概率值创建哈夫曼树.第三步:对哈夫曼树进行编码,并把编码后得到的码字存储起来.因为定长编码已经用相同的位数这个条件保证了任一个字符的编码都不会成为其它编码的前缀,所以这种情况只会出现在变长编码当中,要想避免这种情况,我们就必须用一个条件来制约定长编码,这个条件就是要想成为压缩编码,变长编码就必须是前缀编码.什么是前缀编码呢。字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到。哈夫曼编码是一种可变长的编码,它依据字符出现的概率来决定字符编码的长度,使得出现概率大的字符编码长度短,出现概率小的字符的编码长度长,于是可以减少整体的编码的长度。
不断的进行这个过程直到所有符号编码完毕。 ps *= Sp[i]; //求 Ps } cout << "Fs=" << Fs << endl;//显示最终的算术编码 gFs = Fs; out << "算术编码结果:" << endl; out << "Fs=" << Fs << endl; float l = log((float)1 / ps) / log((float)2);//计算算术编码的码字长度 l if (l>(int)l)l = (int)l + 1; else l = int(l);//将 Fs 转换成二进制的形式 int d[20]; int m = 0; while (l>m) { Fs = 2 * Fs; if (Fs>1) {Fs = Fs - 1;d[m] = 1; } else if (Fs<1)d[m] = 0; else { d[m] = 1; break; } m++; } int z = m; //解决有关算术编码的进位问题,给二进制数加 if (m >= l) { while (1) {d[m - 1] = (d[m - 1] + 1) % 2;//最后位加if (d[m - 1] == 1)break;else m--; }} cout << "s="; out << "s="; for (int e = 0; e < z; e++) { cout << d[e]; out << d[e]; } cout << endl; out << endl; } //解码程序 void jiema(int a, int h) { int i; float Ft, Pt; float Fs = 0, Ps = 1; out << "算数译码后:"; for (i = 0; i<h; i++)//以编码个数和符号个数为循环周期对其进行解码 { for (int j = a - 1; j>-1; j--) {Ft = Fs;Pt = Ps;Ft += Pt*f[j];//对进行逆编码Pt *= P[j];if (gFs >= Ft)//对其进行判断并且将值存入到数组 A 中{Fs = Ft;Ps = Pt;cout << A[j];out << A[j];break;} } } cout << endl; out << endl; } void main() { cout << "编码个数";int a, i, h = 0; in >> a; cout << a << endl; cout << "输入编码符号和概率值" << endl; for (i = 0; i < a; i++) { char x; float y; in >> x; cout << x; A[i] = x;//将字符依次存入数组 A 中 in >> y; cout << y << endl; P[i] = y;//将字符所对应的概率依次存入到数组 P 中 } for (i = 1; i < a; i++) { f[0] = 0; f[i] = f[i - 1] + P[i - 1];//将要编码的数据映射到一个位于[0,1)的实数区间中 } while (!in.eof()) { cout << "输入需要编码的符号序列,同时用$结尾" << endl; h = 0; while (1)//这个 while 语句的作用是将要编码的字符存入到数组 S 中 {char cc;in >> cc;if (cc == '$')break;//在以“$”为结尾的时候结束存储S[h++] = cc;cout << cc; } cout << endl; cout << "算术编码结果:" << endl; bianma(a, h); cout << "对应的解码结果:" << endl; jiema(a, h); system("pause"); } in.close(); out.close(); } 4. 二个号序该码短,5. 时候用到核心算出的多快。
用后者的方法,可以这样建立二者之间的映射:二进制序列每4个为一组,用8421bcd码编码,4位对应实数中的一位,再用1111表示小数点,这样每个实数总能映射到一个唯一的二进制序列,既然实数集不可数,那么无限二进制序列也不可数。后者的操作对象是三元而非二元数字,三元golay码将每6个三元符号分为一组,编码生成5个冗余校验三元符号,这样由11个三元符号组成的三元golay码码字可以纠正2个错误。每个符号被转换成码片的数目叫扩频因子sf(spreading factor) 加扰:用一个伪随机序列与扩频后的序列相乘,起到加密作用,扰码码片速率与已扩频的符号相同,不影响符号速率。
杨洋加油