【11】二进制编码:“手持两把锟斤拷,口中疾呼烫烫烫”?
- 推荐阅读:《编码:隐匿在计算机软硬件背后的语言》
引言
一、理解二进制的“逢二进一”
-
二进制转10进制: 0011【二进制数】, 0×23+0×22+1×21+1×20=3【0011对应的十进制数】
-
10进制转2进制【短除法】
- 比如,我们想把 13 这个十进制数,用短除法转化成二进制,需要经历以下几个步骤:因此,对应的二进制数,就是 1101。
- 比如,我们想把 13 这个十进制数,用短除法转化成二进制,需要经历以下几个步骤:因此,对应的二进制数,就是 1101。
-
原码表示法
- 正数:0011【代表3,首位0代表正数】
- 负数:1011【代表-3,首位1代表负数】
- 问题:1000和0000都代表0,浪费了1个数
-
引出补码【首位为1时,是负数,转为10进制时,在最左侧加个负号】
- 实例:一个 4 位的二进制补码数值 1011,转换成十进制,就是 −1×23+0×22+1×21+1×20
- 求十进制补码的方法【取反加1】: -5对应带符号位负数5(10000101)→除符号位外所有位取反(11111010)→加 00000001为 (`11111011)0【-5的补码为11111011】
- 当然更重要的一点是,用补码来表示负数,使得我们的整数相加变得很容易,不需要做任何特殊处理,只是把它当成普通的二进制相加,就能得到正确的结果。
二、字符串的表示,从编码到数字
1、 ASCII 码(American Standard Code for Information Interchange,美国信息交换标准代码)
2、二进制序列化要比字符串表示更省内存空间【整数、浮点数等数值的表示】
我们可以看到,最大的 32 位整数,就是 2147483647。如果用整数表示法,只需要 32 位就能表示了。但是如果用字符串来表示,一共有 10 个字符,每个字符用 8 位的话,需要整整 80 位。比起整数表示法,要多占很多空间。
这也是为什么,很多时候我们在存储数据的时候,要采用二进制序列化这样的方式,而不是简单地把数据通过 CSV 或者 JSON,这样的文本格式存储来进行序列化。不管是整数也好,浮点数也好,采用二进制序列化会比存储文本省下不少空间。
3、引入Unicode字符集
ASCII 码只表示了 128 个字符,一开始倒也够用。然而随着越来越多的不同国家的人都用上了计算机,想要表示譬如中文这样的文字,128 个字符显然是不太够用的。于是,计算机工程师们开始各显神通,给自己国家的语言创建了对应的字符集(Charset)和字符编码(Character Encoding)。
字符集【一个集合】,表示的可以是字符的一个集合。比如“中文”就是一个字符集,不过这样描述一个字符集并不准确。想要更精确一点,我们可以说,“第一版《新华字典》里面出现的所有汉字”,这是一个字符集。这样,我们才能明确知道,一个字符在不在这个集合里面。比如,我们日常说的 Unicode,其实就是一个字符集,包含了 150 种语言的 14 万个不同的字符。
字符编码【一套转换规则】,则是对于字符集里的这些字符,怎么一一用二进制表示出来的一个字典。我们上面说的 Unicode,就可以用 UTF-8、UTF-16,乃至 UTF-32 来进行编码,存储成二进制。所以,有了 Unicode,其实我们可以用不止 UTF-8 一种编码形式,我们也可以自己发明一套 GT-32 编码,比如就叫作 Geek Time 32 好了。只要别人知道这套编码规则,就可以正常传输、显示这段代码。
4、“手持两把锟斤拷,口中疾呼烫烫烫”的原因?【乱码问题】
乱码的本质:编码和解码不一致
总结【个人总结的重点】
-
原码表示法有一个很直观的缺点就是,0 可以用两个不同的编码来表示,1000 代表 0, 0000 也代表 0。
-
用补码来表示负数,使得我们的整数相加变得很容易,不需要做任何特殊处理,只是把它当成普通的二进制相加,就能得到正确的结果。
-
补码的实际应用:二进制转十进制【二进制为负数】;十进制负数转二进制【取反加1】
-
反码通常是用来由原码求补码或者由补码求原码的过渡码。
- 反码跟原码是正数时,一样(0001的反码是0001);负数时,反码就是原码符号位除外,其他位按位取反。(1001的反码是1110)
-
我们日常说的 Unicode,其实就是一个字符集,包含了 150 种语言的 14 万个不同的字符。
-
字符集(Charset):一个字符集合。
-
字符编码(Character Encoding):一套 字符和数值 的 转换或对应规则。
-
而字符编码则是对于字符集里的这些字符,怎么一一用二进制表示出来的一个字典。我们上面说的 Unicode,就可以用 UTF-8、UTF-16,乃至 UTF-32 来进行编码,存储成二进制。
-
乱码的问题其实是编码和解码不一致的问题