计算机编码

来自智得网
跳转至: 导航、​ 搜索

简介

二进制和十进制的互相转换

在早期机械的计算装置中,计算器是辅助人脑进行计算的,所以使用的都是十进制,例如西方发明的手摇机械计算器利用内部精密的齿轮完成计算,齿轮上的10个格子代表数字,从第一个格子1以此类推至第9个格子代表9,转动一圈完成进位计算,将此类齿轮级联10个可以表示0到999999999的数字。再配合其他的机械设备,就可以实现加减乘除的计算。

中国的算盘也是十进制的计算器,传统的算盘每一个格子分上下两栏,下方5个算珠每个代表1,上侧2个算珠每个代表5,所以算盘的每一格表示10。

十进制计算器和人类数学的知识体系是相通的,所以中间不需要进行额外的转码操作。

电子计算机的发明使得十进制的表达出现了困境,电子元件只有开和关两种基本的状态,表达十进制过于复杂。物理限制决定了以电子管为基础的电子计算机采用二进制来存储和表达数据。

计算机使用二进制有以下优点:

  • 电路中容易实现
    • 当计算机工作期间,电路通电工作,每个输出端就有了电压。电压的高低通过模数转换很方便转换为二进制,例如高电平(一般3.2伏以上)表示1,低电平(一般2.5伏以下)表示0,模拟电路转换成为数字电路就实现了二进制的转换。
  • 物理存储方便实现
    • 二进制在物理上最易实现存储,通过磁极的取向、表面的凹凸、光照的有无等可以实现数据存储。例如光盘,就是将激光束聚集为小光束融化盘片表面上的合金薄膜形成凹坑来记录1的,而没有被激光照耀过的位置可以记录0。

计算机使用二进制表示信息例如数字,但是人类数学知识体系中的数字是用10进制表达的,表达方式的差异就需要进行编码。

原理

计算机的编码解码流程

计算机世界只有0和1两个数字,但是需要表现的信息如此的复杂,从计算程序使用的数字到表现各种信息的字符,英文字符,中文字符,拉丁字符等,还有各种声音的信息,图像的信息,视频信息需要存储和表示,这些信息经过多次编码转换以及设备的输入输出才能在计算机体系中展示如此丰富的信息。

  • 信息首先经过输入码的转换,将客观世界的信息转换为数字编码。
  • 输入码通过输入设备达到计算机的存储设备。
  • 存储设备存储数据的编码称为内码。
  • 内码经过一定的转换变成输出设备需要的编码,称为输出码。
  • 输出码在不同的输出设备上展现不同的信息。

用汉字输入为例:

  • 常用的汉字输入法例如拼音输入和五笔输入法将汉字转为字符序列的编码,这就是输入码,也称为外码。
  • 汉字在计算机中可以使用UTF-8等编码进行存储,这些编码的字符集就是内码。
  • 要在显示设备上展示汉字,还要将这些文字变成可视化的图形,这些就是字型码,也称为字模。
  • 交换码是指计算机和别的计算机交换信息时使用的编码。

本文主要介绍计算机内存储信息的内码,分别从数字,字符,多媒体的编码进行介绍。

数字的编码

整数编码

整数的表达分为两部分,数值的表达以及符号的表达。

对于数值的表示,十进制每一位可以有 0-9 十个数字,逢10进一,而二进制每一位只能有0和1两个数字,逢2进一。所以第n位二进制的值an(0或者1)对应十进制世界的值是an*2n

所以二进制到十进制的转换可以如下表示:

anan-1...a2a1a0(二进制)=a0*20+a1*21+a2*22+an-1*2n-1+an*2n(十进制)

反之十进制转换为二进制,可以使用辗转相除法。

数学概念中,使用+,-等符号作为正负数标识参与运算,但是计算机只有0和1,规定最高位为0代表正数,最高位1代表负数的编码方式也称为原码。

原码在数学领域是否是一个自洽的概念,下面的例子说明了原码存在缺陷:

原码在计算出现溢出时候会出现不合理的结果,例如5-3=5+(-3)=0101+1011=10000=0000=0。

在原码基础上,如果是负数的话,对除了符号位之外的数字均取反,也就是反码。

反码在计算出现溢出时候结果依然不正确,例如5-3=5+(-3)=0101+1100=10001=0001=1。

目前计算机内存储数字使用的都是补码,补码的定义如下:

  • 正数的补码为其本身,负数补码除了符号位将所有位置的数字取反,再加1.
  • 符号位权的总和,符号位权值为2的n次方,最高位权值带符号
    • 数字系统的模减去数字本身得出的数字就是补码
补码在计算出现溢出时候依然有正确的结果,例如5-3=5+(-3)=0101+1101=10010=0010=2。
浮点数编码

目前计算机中多采用IEEE确定的浮点存储标准算法,浮点的整数用2的指数来表达压缩,小数用2的负指数来表达压缩。

以18.625的float存储为例,逐条具体分析:

  • 整数部分的2进制转换使用辗转相除法。
    • 18的二进制结果是10010
  • 小数的二进制转换是乘2取整,直到乘2的结果为1
    • 0.625x2=1.25,取整1,1对应的权重是2-1=0.5
    • 0.25x2=0.5,取整0,0对应的权重是2-2=0.25
    • 0.5x2=1,取整1,1对应的权重是2-3=0.125
    • 从前往后按照权重由大到小,二进制的结果为101,2-1+2-3=0.625
  • 18.625的整数部分和小数部分合在一起时10010.101。
  • 将上述结果转为科学记数法,也就是1.0010101*24
    • 将指数4加上127做偏移,指数也就是131,转为二进制的结果为 10000011
  • 浮点数最终表示的方式是,符号位+指数部分+尾数部分+补零

18.625转换为浮点数最终结果也就是0 - 10000010 - 0011101 - 00000000

因为浮点数的误差是因为每一位只能表示(½)n,所以浮点数的小数部分并不能表达所有的数字,用浮点数运算会产生精度问题。

字符编码

ASCII码表

字符(Character) 是对文字和符号的总称,例如汉字、拉丁字母、emoji 都是字符。

针对字符有不同的编码方式,也就是字符集。

ASCII码

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是对西方文字最常用的编码方式,在ASCII中规定:一个字节所对应一个符号。在计算机中,一个字节包含8位,一个字节所能表示的不同状态也只有256个,在ASCII字符集中,只有128个符号,其中前32个符号,是非显示字符(换行符、制表符、响铃等)。

随着计算机发展到其他地区,因为不同地区有不同的语言体系以及字符体系,所以不同地区就发展出了其他的编码体系。

欧洲人对ASCII进行了拓展,把剩下的128个也和欧洲地区的字符建立了对应关系,命名为EASCII。

类ASCII码因为只有一个字节,所以仅能表达256个字符,但是中文有近8万个字符,为了让计算机可以处理中文,中文也有了自己的编码体系。

GB2312

1980年中国国家标准总局发布了《信息交换用汉字编码字符集基本集》,标准号为GB 2312-1980,该标准在中国大陆以及新加坡地区有广泛的使用,也称为国标码。

GB 2312是一个简体中文字符集,字符集内有6763个常用汉字和682个全角的非汉字字符组成。其中汉字根据使用的频率分为两级,一级汉字3755个,二级汉字3008个。GB2312采用了一个94行94列的二维矩阵编码法对字符进行编码。对每一行称为一个区,每一列称为一个位。

为了避免和ASCII出现冲突,GB2312使用字节的首位作为区分,首位为0则表示ASCII字符,否则表示GB2312中的字符。GB2312编码时将区位码的每个字节分别加上A0H(160)的方法转换为存储码,字符的区码和位码分别加上 A0H,位码在前区码在后连在一起就是GB2312编码。

GB2312的区码和位码分别占一个存储单元,每个汉字占两个存储单元。

Unicode编码集

为了解决不同地区使用各自字符编码方案的局限,世界各地主要的电脑制造商、软件开发商、数据库开发商、政府部门、研究机构、国际机构、各用户组织及个人组成了统一码联盟,统一码联盟发布了 Unicode 编码方案,Unicode编码对每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

Unicode 不对人类语言的字符编码,还对部分文学创作的语言例如《魔戒》中的精灵语文字,《星际迷航》中克林贡人使用的文字进行编码

目前的Unicode编码长度是21位,可以表达的字符数高达一百多万,这一百多万个编码称为码点,码点被划分成 17 个大小相同的平面(编号 0 ~ 16),每个平面可容纳 216 即 65,536 个码点。

其中平面0(Plane 0)也称为BMP是最重要的平面,世界上最常用的字符都在该平面中,Plane 2 和 Plane 3 主要供汉字扩展用;最后两个平面是私有编码空间(PUA),不分配确定码点,应用可以自定义使用。

平面又可以根据内容的差异划分成块(block),每个块都是同一种语言的字符,例如平面0的 0000~007F 是基本的拉丁字母(ASCII 字母),0590~05FF 是希伯来文,4E00~9FFF 是中日韩统一表意文字(最常用的汉字基本都在改区域)。

Unicode定义了字符的编码集,但是每个字符具体如何存储,例如每个字符占用的空间大小没有明确定义。所以基于Unicode出现了一系列的编码方案,这些编码方案在空间占用以及编码效率上存在差异。

编码方式 长度(字节) 编码方案 优点 缺点
UTF-8 1~4变长字节 不同范围的码点使用不同长度的编码,不同长度的编码利用前缀区分。

字节编码长度为 1 时前缀为0,长度为 2 时前缀为110,长度为 3、4 时前缀分别是1110和11110。 除首字节外的其余字节的前缀为10。

编解码效率较低 空间占用最大
UTF-16 2或者4字节 基本平面的码点(编号范围在U+0000~U+FFFFF)使用 2 个字节表示。

其他平面(辅助平面)的码点(编号范围在U+10000~U+10FFFF的码点)使用 4 个字节表示。 16 个辅助平面共220个字符,需要 20位的空间区分。为了错开基本平面的码点,UTF-16将20位拆为2部分:

  • 高 10 位映射在 U+D800 ~ U+DBFF,称为高位代理(high surrogate);
  • 低 10 位映射在 U+DC00 ~ U+DFFF,称为低位代理(low surrogate)。
编解码效率中等 空间占用中等
UTF-32 4字节定长 Unicode的码点最多3字节,所以UTF-32直接使用改码点,剩余的位数直接补0。 编解码效率最高 空间占用最大

多媒体编码

视频和音频的数据量一般比较大,例如RGB格式存储的25帧率的720p视频,每秒的数据量高达1Byte*3*1280*720*25=69MB/s,所以多媒体编码的主要作用是在不损失视觉体验的情况下,尽量压缩数据。

常见的视频编码有H.261、MPEG-1、JPEG、MPEG-2、H.263、MPEG-4、H.264/MPEG-4 AVC、H.265/HEVC、VP8/VP9、VC-1、AVS/AVS+/AVS2

常见的音频编码方式有PCMU、PCMA、ADPCM、LPC、CELP、G.711、G.721、G.722、MPEG-1 audio layer 1、MP3、AAC