2.2字符与字符串
2026-03-14这节很简单哦~上一节很累了,这一节全是小百科~我们交给D老师的小总结~
1. BCD 码
**BCD 码**,全称是 **Binary-Coded Decimal**,即**二进制编码的十进制**.
#### 1.1 它要解决什么问题?
计算机内部所有数据都使用二进制.但是,二进制小数(如 `0.1`)在转换为二进制浮点数时,往往是无限循环的,会导致精度丢失.这对于**金融,商业,会计**等需要精确十进制计算的领域来说是致命的.
BCD 码就是为了解决这个问题:**用二进制来精确表示每一位十进制数字**.
#### 1.2 它是如何工作的?
最常用的是 **8421 BCD 码**.它的规则很简单:用 **4位二进制数** 来表示 **1位十进制数**.(rightarrow是右箭头→)(我懒得改了~)
- **数字 5**:二进制 `0101` \(\rightarrow\) BCD 码 `0101`
- **数字 8**:二进制 `1000` \(\rightarrow\) BCD 码 `1000`
- **数字 12**:二进制是 `1100`,但在 BCD 码中,需要把它拆成两位:
- 1 \(\rightarrow\) `0001`
- 2 \(\rightarrow\) `0010`
- 所以 12 的 BCD 码是 `0001 0010`
#### 1.3 特点
- **优点**:可以**精确,无误差**地表示十进制小数.比如 `0.1` 在 BCD 中可以精确表示为 `0001`,而不会像浮点数那样产生近似值.
- **缺点**:浪费存储空间.本来 8 位二进制可以表示 0-255(共 256 个数),但用 BCD 码只能表示 0-99(共 100 个数).同时,算术运算也更复杂,CPU 需要专门的指令来对 BCD 码进行"十进制调整".
---
### 2. 汉字 GBK 码
**GBK** 是汉字字符集及其编码标准,全称是 **《汉字内码扩展规范》**(Guo Biao Kuozhan,即"国标扩展").
#### 2.1 它要解决什么问题?
早期计算机用 ASCII 码只能表示英文.为了让计算机能处理中文,必须为成千上万个汉字规定唯一的编码.
#### 2.2 它是如何工作的?
- **基础**:GBK 向下兼容最早的 **GB2312** 标准,并进行了扩展.
- **编码方式**:它是一种 **双字节编码**.即用 **两个字节(16位)** 来表示一个汉字.第一个字节称为"区",第二个字节称为"位",组合起来就能定位到数万个汉字.
- **兼容性**:GBK 的设计非常巧妙,它完全兼容 ASCII 码.如果一个字节小于 127,它就被解释为一个英文字符;如果一个字节大于 127,它就和下一个字节一起组成一个汉字.
#### 2.3 历史地位
GBK 曾经是 Windows 等操作系统中简体中文版的默认编码,应用非常广泛.后来,为了能在全球范围内统一表示所有文字,**Unicode(特别是 UTF-8)** 逐渐取代了它.不过,你有时仍会在一些旧系统或文本文件中看到它.
*余3码**和**2421码**都是**BCD码**的变种(即用二进制编码表示十进制数字),但它们的设计思路和权重分配不同.以下是它们的核心区别:
---
### 1. 余3码
- **定义**:在8421 BCD码的基础上**加3**(即二进制`0011`)得到的码.
- **编码方式**:
- 十进制数字 \(d\) 的余3码 = \(d\) 的8421码 \(+\ 3\).
- 例如:0(`0000`)→ `0011`;1(`0001`)→ `0100`;9(`1001`)→ `1100`.
- **特点**:
- **自补特性**:对9的补码(9-d)的余3码等于原数字余3码的**按位取反**.例如:3(`0110`)取反得 `1001`,对应6(因为9-3=6),这在硬件实现减法时非常方便.
- **无全0/全1**:避免了全0或全1的编码,有利于早期电路检测错误.
- **应用**:常用于十进制数字的算术运算(尤其是减法),以及早期计算机的十进制计算.
---
### 2. 2421码
- **定义**:一种有权码,各位权重从高位到低位分别为 **2,4,2,1**.
- **编码方式**:
- 每个十进制数字用4位二进制表示,按权重2-4-2-1计算其数值.(times是乘以)
- 例如:数字5 → 可以编为 `1011`(因为 \(1\times2 + 0\times4 + 1\times2 + 1\times1 = 2+0+2+1=5\)).
- 注意:2421码的编码不是唯一的(例如5也可编为 `0101`),但通常选用**满足"对9自补"的编码**,即规定0~4的编码,5~9的编码由0~4按位取反得到.
- **特点**:
- **对9自补**(与余3码类似):例如0(`0000`)取反得 `1111`,对应9(9-0=9);3(`0011`)取反得 `1100`,对应6(9-3=6).
- **有权码**:可以按位计算数值,便于某些电路实现.
- **应用**:同样用于需要自补特性的十进制运算,有时也用于数字显示或键盘编码.
国标码加8080h"是中文信息处理中非常经典的一个步骤,它连接了**国标码**和**机内码**这两个概念.简单来说,这是为了在计算机系统中**区分汉字和英文字符**而做的一个必要转换.
以下是详细的讲解:
### 1. 背景:为什么需要加 `8080H`?
在计算机的早期阶段,英文(ASCII)是单字节编码,一个字节最高位是0.为了在同一个系统中既能处理英文,又能处理中文,必须保证**汉字编码不与ASCII码冲突**.
- **国标码**(如GB2312)虽然为汉字分配了"区"和"位",但它的编码范围在 **`2121H` ~ `7E7EH`** 之间.
- **问题**:这个范围的低位(`21H`)和ASCII码中的可显示字符(如`21H`是感叹号`!`)有重叠.如果直接用国标码传输,计算机无法判断一个字节是ASCII字符,还是汉字的一半.
### 2. 操作:加 `8080H` 的作用
为了解决这个问题,设计者将**国标码的每个字节最高位都置为1**.因为 `80H` 的二进制是 `1000 0000`,所以:
> **机内码 = 国标码 + 8080H**
- **国标码 `2121H`**(二进制:`0010 0001 0010 0001`)
- **加上 `8080H`**(二进制:`1000 0000 1000 0000`)
- **得到机内码 `A1A1H`**(二进制:`1010 0001 1010 0001`)
转换后,两个字节的最高位都变成了1.当计算机读取到最高位为1的字节时,就知道它不是普通的ASCII码,而是汉字编码的一部分.
### 3. 实际流程
假设你输入一个汉字"啊":
1. **区位码**:`1601`(16区01位).
2. **国标码**:在区位码基础上加 `2020H`,得到 `3021H`.
3. **机内码**:在国标码基础上加 `8080H`,得到 **`B0A1H`**.这个 `B0A1H` 才是最终存储在计算机和文本文件中的值.
### 4. 为什么要强调这个操作?
在逆向工程或底层编程中,如果你从内存中读取到一串二进制数据(比如 `B0A1`),想要查它对应的汉字,就需要反向操作:
> **国标码 = 机内码 - 8080H**
然后通过国标码去查表,才能定位到"啊"字在GB2312字库中的位置.
### 总结
**加 `8080H` 是为了将国标码转换为计算机内部实际使用的机内码,通过将两个字节的最高位都设为1,来区分汉字与ASCII字符.**
*校验码**是一种用于**检测或纠正数据在传输或存储过程中是否发生错误**的编码技术.它通过在原始数据的基础上附加额外的冗余信息(校验位),让数据具有一定的"自检"能力.
可以把原始数据想象成一段信息,校验码就是这段信息的"**指纹**"或"**冗余备份**",接收方可以比对指纹来判断信息是否被篡改.
以下是几种常见的校验码及其核心区别:
### 1. 奇偶校验码(最简单的校验)
- **原理**:在数据末尾加上1位校验位,使整个数据(包括校验位)中"1"的个数为**奇数(奇校验)**或**偶数(偶校验)**.
- **例子**:
- 传输数据 `1011`(其中有3个1,奇数个).
- 如果约定使用**偶校验**,则需要加一个校验位 `1`,使1的总数变成4个(偶数).传输的数据变为 `10111`.
- 接收方收到后,数一下1的个数.如果是奇数,说明数据肯定出错了.
- **优缺点**:实现简单,但只能检测出奇数位的错误(比如1位,3位出错),如果两位同时翻转(如 `11` 变成 `00`),1的个数奇偶性不变,就无法检测出来.它也没有纠错能力.
### 2. 循环冗余校验码(最常用的校验)
- **原理**:将数据看作一个很长的二进制数,约定一个除数(生成多项式),用这个除数对数据进行二进制除法运算,得到的**余数**就是CRC校验码.接收方用同样的除数再除一遍,如果余数不为0,说明数据出错.
- **例子**:在网络传输(以太网),压缩文件,存储设备中广泛应用.它能检测出大量错误,但通常不用于纠错,出错就请求重传.
- **优缺点**:检错能力非常强,硬件实现简单,是数据通信中最主流的校验方式.
### 3. 海明码(能自动纠错的校验码)
- **原理**:在数据中插入多个校验位,这些校验位不仅负责整体校验,还通过特定的位置关系,覆盖不同的数据位.当某一位出错时,相关的几个校验位会同时报错,通过它们的组合就能**精确锁定是哪一个数据位发生了错误**,进而自动取反纠正.
- **例子**:主要用于内存(如早期的ECC内存)和对数据可靠性要求极高,但无法请求重传的场景(如某些太空探测器的数据传输).
- **优缺点**:不仅能检测错误,还能**自动纠正**(通常是单比特纠错),但冗余开销较大.
### 总结:三种校验码的区别
| 类型 | 核心操作 | 检错能力 | 纠错能力 | 应用场景 |
| :--- | :--- | :--- | :--- | :--- |
| **奇偶校验** | 数1的个数 | 只能检测奇数位错误 | 无 | 早期内存,简单的串口通信 |
| **CRC校验** | 二进制除法取余 | 极强(能检测突发错误) | 无 | 网络数据包,磁盘存储 |
| **海明码** | 多位交叉校验 | 强 | **有(单比特纠错)** | ECC内存,对延迟敏感的场景 |
**简单概括:**
- 如果只是想知道数据有没有**被弄乱**,用**CRC**.
- 如果数据乱了**必须现场修复**,没时间重传,用**海明码**.
- 如果成本敏感且错误概率低,偶尔用**奇偶校验**.
了解即可~