算是读书笔记吧
极客时间--深入浅出计算机组成原理
二进制编码
二进制和我们平时用的十进制,其实并没有什么本质区别,只是平时我们是“逢十进一”,这里变成了“逢二进一”而已。每一位,相比于十进制下的 0~9 这十个数字,我们只能用 0 和 1 这两个数字。
-
二进制转十进制
从右到左的第 N 位,乘上一个 2 的 N 次方
0011 =>> 0×2³+0×2²+1×2¹+1×2⁰ = 3
-
十进制转二进制
用2做短除法
因此13这个十进制数,对应的二进制数,就是 1101。
-
原码表示法
一个二进制数最左侧的一位,当成是对应的正负号,比如 0 为正数,1 为负数,这样来进行标记。
0011 表示 +3、1011表示 -3
但是对于0:1000 代表 0, 0000 也代表 0。
-
补码表示法
一个二进制数最左侧的一位,表示-1ⁿ
1011 换算成十进制为:−1×2³+0×2²+1×2¹+1×2⁰=−5
0000 表示 0,1000 在这样的情况下表示 -8。
字符编码
-
ASCII 码
ASCII 码就好比一个字典,用 8 位二进制中的 128 个不同的数,映射到 128 个不同的字符里。
比如,小写字母 a 在 ASCII 里面,就是第 97 个,也就是二进制的 0110 0001,对应的十六进制表示就是 61。而大写字母 A,就是第 65 个,也就是二进制的 0100 0001,对应的十六进制表示就是 41。
在 ASCII 码里面,0-9每一个数字都对应这一个8位编码。所以很多时候我们在存储数据的时候,要采用二进制序列化这样的方式,而不是直接用CSV 或者 JSON进行存储。
-
字符集(Charset)
字符集,表示的可以是字符的一个集合
我们日常说的 Unicode,其实就是一个字符集,包含了 150 种语言的 14 万个不同的字符。
随着计算机的普及,越来越多的语言加入了Unicode。
现在,他用32位,4个字节表示一个字符。
-
字符编码(Character Encoding)
类似一种传输协议,对
Unicode
编码后的编号进行压缩。
Unicode本身的字符集是32位的,那么每个字符都用4个字节传输,对欧美而言,一下就要用原来ASCII码时代四倍的资源传输或者保存一样的文档
。于是,出现了uft-8,utf-16,utf-32这些编码方案。
把字符的代码通过这个编码方式映射成传输时的编码,在使用Unicode字符集保持通用性的同时节约流量和硬盘空间。
-
UTF-8编码
UFT-8编码可以保证最大限度的节约空间
相对于Unicode这种大家固定的UTF-8的编码称之为变长码。其大受欢迎的主要原因就是对欧美而言,在保留Unicode通用性的情况下避免了流量和空间的浪费。
用UTF-8在接收时,接到一个编码如果是合法的8位编码,就可以直接把它判定为字符,这就给了Unicode字符集在表示英语时和ASCII一样的效率。如果是不合法的,那继续读一个字节,读的两个字节16位如果是合法的,判别为一个字符,再不行继续读下去。
- 为什么UTF-8成为主流
计算机世界绝大部分传输的都是英文以及数字,编码之后UTF-16要两倍于UTF-8的空间
- 为什么计算机不直接使用UTF-8进行编码
UTF-8虽然更加节省空间,但是解析起来相对定长编码更加麻烦。
不从头扫描一遍,你不知道第几个字符在哪个位置上,这在处理的时候非常浪费时间。
现在很多语言/程序的处理办法,是使用源于原始UTF-16的一个定长编码,只处理字符码在16位以内的字符,不支持超过16位的罕见字。这种16位定长的编码方式被称为UCS-2。
-
锟斤拷
`未知字符` ==(**Unicode**)==> `U+FFFD` ==(**UTF-8**)==>`\xef\xbf\xbd`
`\xef\xbf\xbd\xef\xbf\xbd` ==(**GB2312**)==> `锟斤拷`
-
GBK
是汉字专用的字符编码方式
GBK、GB2312等与UTF8之间都必须通过Unicode编码才能相互转换:
GBK、GB2312--Unicode--UTF8
UTF8--Unicode--GBK、GB2312
-
烫烫烫
如果你用了 Visual Studio 的调试器,默认使用 MBCS 字符集。“烫”在里面是由 0xCCCC 来表示的,而 0xCC 又恰好是未初始化的内存的赋值
定点数
一种二进制来表示十进制的编码方式
-
BCD 编码(Binary-Coded Decimal)
我们把最右边的 2 个 0~9 的整数,当成小数部分;把左边 6 个 0~9 的整数,当成整数部分。这样,我们就可以用 32 个比特,来表示从 0 到 999999.99 这样 1 亿个实数了。
它的运用非常广泛,最常用的是在超市、银行这样需要用小数记录金额的情况里。在超市里面,我们的小数最多也就到分。这样的表示方式,比较直观清楚,也满足了小数部分的计算。
浮点数
float类型
-
IEEE 的标准
它定义了两个基本的格式
- 用 32 比特表示单精度的浮点数,也就是我们常常说的 float 或者 float32 类型。
- 用 64 比特表示双精度的浮点数,也就是我们平时说的 double 或者 float64 类型。
-
单精度float的表示
单精度的 32 个比特可以分成三部分:
- 符号位
s
1 个比特 -- 记做(−1)^s
- 有效数位
f
23 个比特 -- 记做1.f
- 指数位
e
8 个比特 -- 记做2^(e)
综合科学计数法,我们的浮点数就可以表示成下面这样:
当然,有一些特殊的表示:
举个例子:
-
计算一个浮点数
1. 整数部分
与十进制相同。除以 2,然后看余数
2. 小数部分
乘以 2,然后看看是否超过 1。如果超过 1,我们就记下 1,并把结果减去 1,进一步循环操作。
知道结果等于0
比如9.1、整数位9换算成1001
。
而小数位0.1:
结果是000110011…这里的“0011”会无限循环下去。所以,这也是为什么0.1无法被正确的表示为浮点数的原因。
1001
后拼接上000110011…
也就是 1001.000110011…
进行位移之后为 1.001000110011… × 2^3
-
什么样的数无法被精准的表示成浮点数
二进制能精确地表示位数有限且分母是2^n的小数
比如1/2、1/4、1/8
他们在乘2的循环中,一定有一次能使结果等于1,从而推出循环。
而且,需要在有限位数内完成循环。毕竟有效数位f
只有23个比特。
参考文献
utf-8和Unicode的区别
计算机中为何不直接使用 UTF-8 编码进行存储而要使用 Unicode 再转换成 UTF-8 ?
GB2312、GBK与UTF-8的区别
百度百科--锟斤拷
# 为什么0.1+0.2不等于0.3