news 2026/9/15 5:58:35

MATLAB实现(7,4)循环码编译码与GUI演示

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MATLAB实现(7,4)循环码编译码与GUI演示

简介:这套(7,4)循环码MATLAB实现资源,面向通信工程、计算机科学等专业学生及编码理论初学者,提供带GUI的编译码演示平台,用于快速理解循环码的差错检测与纠正机制。压缩包共3个文件,包含2个MATLAB脚本(.m)和1个图形界面文件(.fig),整体仅18KB,轻量易用,编码、解码及界面展示功能划分清晰。已有536人浏览学习,适合作为信息论与编码课程配套实践工具。借助生成多项式G(x)=x^3+x+1,脚本完整实现4位信息到7位码字的编码与接收纠错解码,GUI支持手动输入信息比特或码字并即时显示结果,便于对照原理观察循环移位特性。在此基础上可修改生成多项式与码长参数,灵活适配更多循环码场景,为课程设计或毕业设计提供可直接运行的参考示例,读者可借此快速验证不同输入序列下的编解码结果。

1. 从一份 74cyclic-code.zip 工程说起

搜到74cyclic-code.zip这个名字的人,多半是在做通信原理课设或数字通信相关项目,里面装的是 (7,4) 循环码的 MATLAB 实现,通常带一个 GUI 交互界面。它解决的核心问题是:把 4 位信息比特用生成多项式编码成 7 位码字送进信道,接收端靠伴随式查表纠正 1 位随机错误,再把信息还原出来。这类工程恰好覆盖了 MATLAB 里最典型的三块技能:GF(2) 多项式运算、查表译码逻辑、GUI 事件回调,也是"matlab 下载安装后找练手项目"的常见去处。适合通信原理课程设计、需要把"循环码"从公式落到可操作程序的工程师,以及想了解 matlab gui 从零搭建一套小工具的人。下面按编码、译码、GUI、参数扩展、验证发布这条链路完整走一遍。

2. (7,4) 循环码编译码的 MATLAB 实现

2.1 生成多项式先写进变量

(7,4) 循环码是汉明码的一种循环码形态,码长 n=7,信息位 k=4,最小汉明距离 d=3,纠错能力 t=1。所有这些性质都由生成多项式 g(x)=x^3+x+1 决定,二进制向量表示是[1 0 1 1]。也有教材选 x^3+x^2+1(向量1101),两者都是 GF(2) 上的本原多项式,都能构成循环码,只是伴随式到错误位置的映射表不同。

提示:MATLAB 的 Communications Toolbox 提供了gfdeconvencodedecode等现成函数,但课设题目通常要求自实现,下面给出的是只用基础 MATLAB 就能跑的算法。

在代码里我一般把生成多项式放在脚本开头作为参数,方便后续替换:

g = [1 0 1 1]; % g(x) = x^3 + x + 1,(7,4) 循环码生成多项式 n = 7; % 码长 k = 4; % 信息位长

参数说明:

  • g向量从最高次到最低次排列,g(1)永远是 1;
  • 校验位数量 n-k=3,恰好等于g向量长度减 1;
  • 判断一个 7 位码字是否合法的依据是它能否被g(x)整除,这就是循环码线性约束的数学形式。

2.2 系统码编码:除以生成多项式取余数

循环码编码常做成系统码:信息位保留在前面,后面拼接校验位。步骤是先把 4 位信息向左移 3 位(等价于乘以 x^3),再对g(x)做模 2 除法,把余数放到尾部。以信息位[1 0 1 0]为例,被除式是 1010000,除以 1011,余数是 011,码字就是 1010011。

模 2 除法里没有借位,减法被异或取代,实现时用循环扫一遍即可:

function [q, r] = polydiv_gf2(a, g) % a: 被除式系数向量,高位在前 % g: 生成多项式系数向量,高位在前 % q: 商,r: 余数 a = a(find(a, 1):end); % 去掉被除式前导 0 g0 = g(find(g, 1):end); % 去掉生成式前导 0 r = [a zeros(1, length(g0)-1)]; % 扩展余数寄存器 q = zeros(1, length(r)); % 商向量,初始全 0 for i = 1:length(r)-length(g0)+1 if r(i) == 1 q(i) = 1; r(i:i+length(g0)-1) = xor(r(i:i+length(g0)-1), g0); end end r = r(end-length(g0)+2:end); % 取最后 length(g)-1 位作为余数 q = q(1:length(a)-length(g0)+1); end

逻辑说明:r(i) == 1说明当前位的剩余部分最高位是 1,需要用生成多项式异或消去;如果r(i)是 0,商这一位记为 0 并继续右移。MATLAB 索引从 1 开始,循环上限length(r)-length(g0)+1保证最后一次异或不会越界。最后r(end-length(g0)+2:end)取的是余数的低 3 位,因为 (7,4) 码余数最高 2 次、正好 3 个系数。

有了除法,编码函数就是移位加取余:

function cw = enc74(msg, g) % msg 是 1x4 的 0/1 行向量,高位在前 shifted = [msg zeros(1, 3)]; % x^3 * m(x),左移 3 位 [~, rem] = polydiv_gf2(shifted, g); rem = rem(end-2:end); % 固定取出 3 位校验位 cw = [msg rem]; % 信息位在前,校验位在后 end

参数说明:rem(end-2:end)比直接用length更稳,因为polydiv_gf2对前导零做了裁剪;如果换成 x^3+x^2+1 同样适用,这一行不用改。

验证一下:对 16 个 4 位信息遍历编码,用除法函数检查每个码字都能被g整除,说明编码过程没有写错,这一步建议在命令行直接跑:

g = [1 0 1 1]; for m = 0:15 msg = de2bi(m, 4, 'left-msb'); cw = enc74(msg, g); [~, r] = polydiv_gf2(cw, g); assert(all(r == 0), '编码结果不合法'); end disp('16 个码字全部通过整除校验');

这段验证用了de2bi,它属于 Communications Toolbox;如果环境里没有,可以用bitget(m, 4:-1:1)替代。

2.3 伴随式译码:一张位置映射表完成定位

接收端拿到 7 位序列 rx 后,直接对g(x)取余数,得到的余数就是伴随式 s(x)。无错误时伴随式为全 0;发生 1 位错误时,伴随式与非零错误图样一一对应,所以只要预先把 7 种单比特错误的伴随式算出来,就能根据 s 反推出错误位置,翻转后取前 4 位恢复信息。

7 位错误位置与伴随式值的对应关系如下表(按 g=1011 计算):

错误位置(MATLAB 索引)错误多项式伴随式二进制 s2s1s0伴随式数值
1(最左位,x^6)x^61015
2x^51117
3x^41106
4x^30113
5x^21004
6x0102
7(最右位,x^0)10011

注意这张表依赖生成多项式,换成 g=1101 时必须重新生成,不能直接套用。表里规律来自 x^3 ≡ x+1 (mod g),手算每一项错误项对这个余数关系化简即可。

译码函数可以这样写:

function msg = dec74(rx, g) % rx: 1x7 接收向量,0/1 [~, s] = polydiv_gf2(rx, g); % 伴随式 = 余数 s = [zeros(1, 3-length(s)) s]; % 左补零到 3 位 s_val = s * [4 2 1]'; % 转成 1~7 的数值 pos_table = [7 6 4 5 1 3 2]; % 下标=伴随式值, 值=出错位MATLAB索引 if s_val ~= 0 err_idx = pos_table(s_val); % 取表定位 rx(err_idx) = 1 - rx(err_idx); % 异或 1 翻转该位 end msg = rx(1:4); % 纠完直接截取信息位 end

逻辑说明:pos_table的下标就是上表的"伴随式数值",例如 s_val=5 查表得 1,表示错误落在最左位,翻转 rx(1)。s_val=0 时不查表,直接跳过。s * [4 2 1]'把多项式系数 x2、x、x0 还原成十进制,等价于二进制转十进制,不需要任何工具箱。

两个边界要说明:第一,如果接收向量发生 2 位及以上错误,伴随式也会落在某个非零值上,查表翻转后会得到错误结果,(7,4) 码只能保证 t=1 的纠错,这是编码理论本身的限制;第二,某些 2 位错误画出来的伴随式恰好在表外,属于不可检测错误,这套机制同样无能为力。

到这里,"编码 → 加错 → 译码"的计算环节就可以在命令行跑通了。把 enc74 和 dec74 放在同一个脚本里,反复模拟 1 位随机翻转,可以稳定看到 msg 原样恢复。

3. 用 MATLAB GUI 把循环码演示做成交互面板

3.1 界面方案选型:App Designer 还是 GUIDE

搜索这套题目的人会碰到很多用 GUIDE 写的 .fig 工程。GUIDE 从 R2019b 开始不再推荐,官方逐步把功能迁移到 App Designer,新写代码建议直接用 App Designer,别再做新的 .fig。App Designer 生成的 .mlapp 本质是类定义文件,界面元素是 properties 里的对象属性,回调函数是 methods 里的成员方法,比 GUIDE 的分散函数结构更好维护,也方便统一管理状态变量。

提示:如果手头是 .fig 老工程,R2021b 之后打开并另存时 GUIDE 会提示迁移,但实际项目里我一般直接重写,迁移过程对 align 和 callback 引用的处理经常比重写还费时间。

App Designer 里新建 Blank App,画布左侧是控件面板,右侧是代码视图。这个循环码演示面板需要 4 个区域:输入区(4 位信息位的编辑框)、编码显示区(7 位码字)、信道干扰区(下拉框选择翻转位置)、输出区(伴随式和译码结果)。控件清单如下:

控件类型名称作用
编辑框InfoEdit输入 4 位 0/1,如 1010
按钮EncodeButton触发编码
文本CodeText显示 7 位码字
下拉框ErrCombo选择 0~7 哪个位置翻转
按钮CorruptButton在码字上翻转所选位
文本RxText显示接收向量
文本SyndText显示伴随式 s2s1s0
按钮DecodeButton触发译码
文本MsgHatText显示译码恢复的信息位

布局上用 uigridlayout 固定行列,避免窗口拉伸时控件乱跑。下拉框的选项值处理与普通 figure 的 uicontrol 略有差异,要留意 Items 和 ItemsData 的配合。

3.2 控件初始化和状态存储

进入 App Designer 的 code view,在 properties 段保存当前码字和生成多项式,这两个状态需要在编码、加错、译码三个回调之间共享:

properties (Access = private) g = [1 0 1 1]; % 生成多项式 cw = zeros(1, 7); % 当前系统码码字 rx = zeros(1, 7); % 当前接收向量 end

在 startupFcn 里初始化下拉框选项,选项的 Value 要和实际比特位置完全对应。这里有个容易踩的坑:下拉框显示"第 3 位"时,用户理解是从左往右第 3 位,而 MATLAB 索引正好也是 3,把选项 Value 直接设成索引就能省掉一次转换:

app.ErrCombo.Items = {'无错误', '第1位', '第2位', '第3位', ... '第4位', '第5位', '第6位', '第7位'}; app.ErrCombo.ItemsData = 0:7; % 0 表示不翻转

ItemsData 是每个选项背后实际存储的值,读取用app.ErrCombo.Value得到的就是 0~7 的数值,不需要在回调里做字符串匹配。

3.3 回调函数:数据从控件流向算法

编码按钮的回调把输入框字符串解析成 4 位向量,调用前面写的 enc74,再渲染到界面:

function EncodeButtonPushed(app, event) str = strtrim(app.InfoEdit.Value); if length(str) ~= 4 || any(~ismember(str, '01')) uialert(app.UIFigure, '请输入4位二进制数,例如 1010', '输入错误'); return; end msg = double(str) - double('0'); % 字符转数值 app.cw = enc74(msg, app.g); % 调用算法层 app.CodeText.Value = sprintf('%d %d %d %d %d %d %d', app.cw); end

逻辑说明:double(str) - double('0')把 '0' 和 '1' 字符统一转成 0/1 数值,这比 str2num 更可靠,str2num 解析 '1010' 会得到一个标量而不是向量;显示时用 sprintf 带空格便于人眼分组。

信道干扰按钮的回调读取 ErrCombo 中用户选的位置,完成翻转:

function CorruptButtonPushed(app, event) idx = app.ErrCombo.Value; % 0~7,0 表示不翻转 if idx == 0 app.rx = app.cw; else app.rx = app.cw; app.rx(idx) = 1 - app.rx(idx); % 翻转所选项 end app.RxText.Value = sprintf('%d %d %d %d %d %d %d', app.rx); end

这里 idx 直接用作 MATLAB 索引,因为 ItemsData 里放的是 1~7。注意每次都要从app.cw重新拷贝再翻转,而不是在上一次的 rx 上继续翻,否则用户多点两次按钮就把两个位都翻转了,超出了 (7,4) 码的纠错范围,界面表现会让人误以为是 bug。

译码回调调用 dec74 并展示中间量:

function DecodeButtonPushed(app, event) msg_hat = dec74(app.rx, app.g); app.MsgHatText.Value = sprintf('%d%d%d%d', msg_hat); [~, s] = polydiv_gf2(app.rx, app.g); s = [zeros(1, 3-length(s)) s]; app.SyndText.Value = sprintf('%d%d%d', s); end

SyndText 显示伴随式的意义在于把译码过程暴露出来:伴随式为 000 表示无错;非零时对应 2.3 节的查表关系。这一步直接把教材里的"查表译码"还原到界面上,正是这类演示工具最常见的用法。

到这里,一个最小闭环已经成立:编码 → 人为翻转 1 位 → 显示伴随式 → 译码恢复。如果还要体现"循环码"的循环性质,可以在界面加一个循环左移按钮,回调里每点一次把cw循环移位一位,并显示移位后仍然能被g整除。这是循环码独有的特征,也是标题里"循环"两个字最容易实操验证的点。

4. 循环码参数边界与工程化扩展

4.1 生成多项式换了,查表就要跟着换

(7,4) 循环码的另一个常用生成多项式是 x^3+x^2+1(向量 1101),它与 x^3+x+1 互为对偶关系,生成的码集合不同,伴随式查找表也不同。网上很多代码把表写死成常数数组,换多项式后译码直接错位,这是最常见的坑之一。

如果要把 GUI 里的生成多项式做成可下拉选择,我的做法是运行时动态生成查表,而不是维护两份手算表。用穷举生成:

function pos_table = build_table(g) n = 7; k = 4; e = eye(n); % 7 个单位错误向量 pos_table = zeros(1, 2^(n-k)-1); % 7 个非零伴随式 for i = 1:n [~, s] = polydiv_gf2(e(i,:), g); s = [zeros(1, 3-length(s)) s]; val = s * [4 2 1]'; pos_table(val) = i; % 伴随式值 -> 错误位置 end end

参数说明:e(i,:)是第 i 位为 1 的错误图样;对每个错误图样求伴随式,把结果 val 作为下标,把位置 i 写入表。如果某个 val 冲突或表里有 0 残留,说明 g 不是本原多项式,(7,4) 结构不成立。这个函数把"换多项式就要改表"的处理自动化了,在 GUI 里切换生成多项式时,只需重新调用它。

4.2 不可检测错误与误用边界

(7,4) 码最小距离 3,只能保证纠正任意 1 位错误。若信道中发生 2 位错误,接收向量除以 g 的伴随式可能恰好等于某个单比特错误的伴随式,译码器会误判成 1 位错误并"纠正"成另一个合法码字,结果是错上加错。这不是代码 bug,是编码增益有限。

表现到 GUI 里很直观:信道误码率高于一定阈值时,界面显示"纠错后"的信息位仍然不对。我做演示时会在界面加一个备注区,提示"本程序针对 BSC 信道单比特错误设计,2 位及以上错误不在保证范围"。如果想提高纠错能力,要把 (7,4) 换成 (15,11) 汉明码或 BCH 码,生成多项式选用 x^4+x+1,编码结构和查表函数完全复用,只要改 n、k、g 三个参数。

4.3 从 7/4 扩展到 15/11 的长码形态

(15,11) 汉明码同样能纠 1 位错误,冗余 4 位,编码效率从 4/7 提升到 11/15。把 enc74/dec74 里的常数抽象成参数 n、k,就能得到通用版本:

function cw = enc_general(msg, g, n, k) r = n - k; % 校验位个数 shifted = [msg zeros(1, r)]; [~, rem] = polydiv_gf2(shifted, g); rem = [zeros(1, r-length(rem)) rem]; % 校验位左补零到 r 位 cw = [msg rem]; end

注意这里的rem = [zeros(1, r-length(rem)) rem],因为余数在实际除法结果里可能不足 r 位,比如余数只有 2 位时需要在前面补一个 0,否则拼接出来的码字不是标准系统码。polydiv_gf2本身对前导零做了裁剪,所以补零这一行不能省。

(15,11) 的伴随式表会膨胀到 2^4-1=15 项,build_table 按伴随式数值做下标,天然支持表长变化,不需要手工改数组。

5. 循环码 GUI 的穷举验证与发布技巧

5.1 全部 112 种场景的自动回归

GUI 回调写完后,不要只靠鼠标点几个 case,最可靠的是写一个脱离界面的穷举脚本,把"16 个信息位 × 7 个翻转位置 = 112 种组合"全部跑一遍:

% verify74.m g = [1 0 1 1]; fail = 0; for m = 0:15 msg = de2bi(m, 4, 'left-msb'); cw = enc74(msg, g); for e = 1:7 % 最多翻转 1 位 rx = cw; rx(e) = 1 - rx(e); msg_hat = dec74(rx, g); if ~isequal(msg, msg_hat) fail = fail + 1; fprintf('失败: msg=%d%d%d%d e=%d\n', msg, e); end end end fprintf('完成,失败 %d 组\n', fail);

这个脚本放在 GUI 工程目录的 test 子文件夹里,每次改动 polydiv_gf2 或查表逻辑后跑一遍,比直接在 App Designer 里点按钮高效得多。如果失败集中在某个特定错误位置,优先怀疑查表;如果全部失败,检查 polydiv_gf2 的余数截断。没有 Communications Toolbox 的环境里,把 de2bi 换成bitget(m, 4:-1:1)即可。

5.2 打包成独立程序给其他人跑

课设验收或把演示交给没有 MATLAB 的同学时,常见做法是导出独立可执行文件。App Designer 的 APP 选项卡里有 Package 按钮,底层调用 MATLAB Compiler 的compiler.build.standaloneApplication,生成的文件需要在目标机器上安装对应版本的 MATLAB Runtime,体积较大但不需要完整 MATLAB。如果对方本身有 MATLAB 环境,导出.mlappinstall安装包更方便,双击即可安装到 App 列表。

提示:打包前清掉 app 里的路径依赖,脚本里不要用cd切目录,运行时的工作目录和开发机不同,任何依赖相对路径的文件都会在对方机器上报错。这类问题在实际打包里出现的概率远高于算法本身出错。

另一个容易让 GUI 卡顿的细节是:在回调里做长循环时要主动调用drawnow,或者把耗时计算放到parfor。对 (7,4) 这种规模完全不需要,但如果你把循环码扩展成更大码长,单次编码虽然是 O(n),GUI 里频繁点按钮重算余数仍然会有肉眼可见的延迟。到了几十毫秒量级就要考虑把计算结果缓存下来,比如把生成多项式 g 和查表结果在启动时算一次放进 properties,回调里只做取数。我把 build_table 放在 startupFcn 里执行就是这个原因。

如果还想给界面增加教学感,可以在 SyndText 旁边加一个文本框,把 polydiv_gf2 的中间异或步骤用字符串打印出来。这样伴随式不再是黑盒结果,而是可以逐位看到除法过程,对理解循环码原理、debug 查表、以及应对答辩提问都有实际帮助。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 5:57:38

DQN2015算法核心架构与实现解析

1. DQN2015算法核心架构解析深度Q网络(Deep Q-Network)作为强化学习领域的里程碑式算法,其2015版在Atari游戏上的突破性表现彻底改变了人们对AI游戏能力的认知。这个算法的核心魅力在于将传统的Q-Learning与深度神经网络相结合,解…

作者头像 李华
网站建设 2026/9/15 5:56:49

中小采购团队为何需要电子招标系统:流程留痕与效率提升

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 5:56:33

机器人一多服务器就崩?从轮询到事件驱动的架构改造实践

做机器人后端这些年,我见过太多“一多就崩”的项目了。所谓的“一多”,往往不是算法算力问题,而是通信方式本身扛不住。具身机器人这东西,一旦数量超过某个临界点,服务器会以一种非常朴素的方式教做人:先 C…

作者头像 李华
网站建设 2026/9/15 5:55:42

AI日报内容生成规范与专业准则说明

我无法根据当前输入生成符合要求的博文。原因如下:项目标题为“AI 日报(2026年9月10日)”,属于未来日期的时效性资讯汇总类内容,但项目正文为空、关键词为空、摘要描述为空,且未提供任何实质性的事件、技术…

作者头像 李华
网站建设 2026/9/15 5:55:23

SVM实战入门:用Iris数据集搞定分类、调参与评估

简介:面向机器学习初学者的SVM分类作业完整方案,采用Python 3.9环境,基于sklearn与numpy实现经典Iris鸢尾花数据集的分类任务。该资源涵盖数据导入、特征展示、模型训练、评估与可视化全过程,帮助读者理解支持向量机在真实数据上的…

作者头像 李华
网站建设 2026/9/15 5:54:32

基于Vue 3 + Vite + Pinia的教材管理前端源码设计与实践

简介:面向学校和教育机构的教材管理前端源码,基于Vue框架设计,聚焦教材资源的数字化登记、检索、信息维护与菜单管理等实际场景,适合正在学习Vue组件化开发的前端初学者,也适合需要快速搭建内部管理后台的开发者参考。…

作者头像 李华