
本文详解如何手动实现 nrz(不归零)编码信号的文本化解码,不依赖任何外部库,重点修复空格截断、行索引错位和电平逻辑反转三大典型错误,并提供健壮、可读性强的参考实现。
本文详解如何手动实现 nrz(不归零)编码信号的文本化解码,不依赖任何外部库,重点修复空格截断、行索引错位和电平逻辑反转三大典型错误,并提供健壮、可读性强的参考实现。
在数字通信教学实践中,NRZ 编码常以 ASCII 示意图形式呈现——通常由 4 行字符构成:顶部信号线(高电平)、中间两条垂直过渡线(含 | 表示跳变点)、底部信号线(低电平)。解码目标是将该波形图逐段映射为二进制比特流:高电平(上横线 _)对应 1,低电平(下横线 _)对应 0;电平变化由 | 字符触发。
原始代码存在三个关键缺陷,导致输出翻转(如 0110 错为 1000):
-
strip()破坏结构:input_scheme.strip()会移除首尾空白行及每行首尾空格,导致第一行(原" ______")被误处理为"______",索引偏移,且丢失关键前导空格信息; -
行索引错位:输入多行字符串使用
split('\n')后,若原始输入以换行开头(如三引号字符串),会产生空首行(''),使nrz_scheme[0]指向空字符串而非实际第一信号线; -
电平逻辑颠倒:误将“上横线存在”判定为
0,但标准 NRZ 图中,上方连续_明确表示高电平1,下方_才表示低电平0。
以下是修正后的完整实现,已通过多个边界用例验证:
def nrz_encoding(input_scheme):
# 正确分割行:跳过首空行(由三引号换行引入),保留所有前导/尾随空格
lines = input_scheme.splitlines()
# 过滤空行并取有效四行(索引 0~3)
nrz_scheme = [line for line in lines if line.strip()][:4]
if len(nrz_scheme) < 4:
raise ValueError("Input must contain exactly 4 non-empty rows representing NRZ diagram.")
index = 0
nrz_output = ''
first_row = nrz_scheme[0] # 上信号线(高电平 → '1')
last_row = nrz_scheme[3] # 下信号线(低电平 → '0')
# 根据最左侧 '_' 判定起始电平(忽略前导空格,但保留位置)
start_char = None
for i, c in enumerate(first_row):
if c == '_':
start_char = 'first'
break
if start_char is None:
for i, c in enumerate(last_row):
if c == '_':
start_char = 'last'
break
if start_char is None:
raise ValueError("No leading underscore found in top or bottom row.")
current_row = first_row if start_char == 'first' else last_row
# 使用实际最大宽度(非 max(len()),因需对齐同一列)
max_length = max(len(first_row), len(last_row))
while index < max_length:
# 在当前列检查哪一行有 '_' —— 决定当前电平
if index < len(first_row) and first_row[index] == '_':
current_row = first_row
elif index < len(last_row) and last_row[index] == '_':
current_row = last_row
# 若均无 '_',保持上一状态(NRZ 保持电平特性)
# 电平映射:上行为1,下行为0
nrz_output += "1" if current_row is first_row else "0"
# 步进:NRZ 图中每个比特占约3列(含过渡区),故 +3
index += 3
# 检查中间过渡行(第1行,即 nrz_scheme[1])是否存在 '|' 跳变标记
if (index < len(nrz_scheme[1]) and
nrz_scheme[1][index] == '|'):
# 遇到跳变,翻转电平(切换 current_row)
current_row = last_row if current_row is first_row else first_row
# 跳过 '|' 字符本身(它占据一列)
index += 1
return nrz_output使用示例:
立即学习“Python免费学习笔记(深入)”;
nrz_input = """
______
| |
| |
___| |___
"""
print(nrz_encoding(nrz_input)) # 输出: "0110"关键注意事项:
- ✅ 绝不使用
strip()处理多行输入:它会破坏列对齐,必须用splitlines()+ 条件过滤; - ✅ 电平定义严格遵循物理意义:上横线 = 高电平 =
1,下横线 = 低电平 =0; - ✅ 跳变检测需结合位置与字符:仅当
nrz_scheme[1][index] == '|'时才触发电平翻转; - ⚠️ 鲁棒性增强建议:生产环境可增加行数校验、跳变位置合法性检查(如
|是否总出现在两横线之间); - ? 调试技巧:在循环中添加
print(f"col {index}: {current_row[index] if index 可直观跟踪解码过程。
该实现完全满足“无 import”要求,逻辑清晰、容错性强,适合初学者理解 NRZ 解码本质——即基于空间位置的状态机建模。


















