1 字符基础 ASCII、Unicode、UTF-8编码
😄学习目标
- 字节与位的关系是什么?表示的范围?
- ASCII、Unicode是什么?
- Unicode与UTF-8、UTF-32关系是什么?UTF-8与UTF-32区别是什么?
- UTF-8编码编码原理
1.1 字节 B、位 b
1字节(Byte, B) = 8位(bit, b)
-
无符号整数(字符编码主要用这个)
- 1B:0到255
- 2B:0到65535
-
有符号整数(模型量化会用到)
- 1B:-128到127
- 2B:-32768到32767
1.2 ASCII、Unicode
计算机底层只有0和1,为显示字符,需要将字符映射为对应整数
-
ASCII
- 逻辑:用1字节存储127个字符(规定了在内存中如何存字符)
- 例子:字符
A对应数字65 - 缺点:无法覆盖中文,从而导致乱码
-
Unicode
- 逻辑:为15万+的字符分配唯一ID,称为码点
- 例子:汉字
牛的码点是29275(转为十六进制0x725b) - 缺点:虽然解决了众多字符的表示问题,但是没有规定在内存中如何存字符
1.3 Unicode、UTF-8与UTF-32
针对Unicode的缺点(如何存字符),UTF (Unicode Transformation Format) 是Unicode的转换格式,负责把字符的数字编号(码点)转换为计算机能够存储的二进制数据(字节流)
总结Unicode、UTF 关系:
- Unicode:给字符分配唯一ID【Unicode像是地图,给字符们分配了地图上的唯一位置坐标】
- UTF:决定计算机如何存字符【在位置坐标ID 上打包字符,存起来】
| 编码方式 | 存储规则 | 优点 | 缺点 | ‘A‘(65)占用 | '牛'(2927) |
|---|---|---|---|---|---|
| UTF-32 | 固定长度 4字节 | 无需计算长度,能够并行处理,速度快 | 浪费空间,所有字符一律4字节 | 4B | 4B |
| UTF-8 | 变长 1-4字节 | 空间效率高,兼容ASCII | 速度较慢,需要顺序遍历 | 1B | 3B |
1.4 UTF-8编码原理
UTF-8采用前缀识别法,即通过字节(二进制流)的前几位来判断该字符占几个字节
(1)编码模板
- 控制位:字节1模板中开头的前几位,如:字节数为3,
1110为控制位 - 延续位:后面字节中开头的前两位,如:字节数为3,
10为控制位
(2)拆解示例:以“牛" 汉字为例
print(ord('牛')) # unicode,取“牛”码点
print(hex(29275)) # 16进制
print(bin(29275)) # 2进制
print('牛'.encode('utf-8')) # 8进制
29275
0x725b
0b111001001011011
b'\xe7\x89\x9b'
1.提取码点: 29275
2.转为十六进制,找字节数:0x725b
- 占3字节,在十六进制码点范围
0800-FFFF
3.转为二进制数,将得到的二进制数按照字节模板来填充:0b111001001011011
-
二进制:
0111 0010 0101 1011(16位) -
填模板
- 模板:
1110 xxxx|10 xxxxxx|10 xxxxxx - 填充:
1110 0111|10 001001|10 011011
- 模板:
-
字节1:
11100111=231(0xE7) -
字节2:
10001001=137(0x89) -
字节3:
10011011=155(0x9B)
4.验证:python最后一行代码运行为b'\xe7\x89\x9b',上文中三个字节正好相同