微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

深入理解计算机系统 第二章

毫无疑问,二进制奠定了计算机操作的基础。我们关注在计算机当中(整数,带符号数,浮点数)他们是如何存储和表示的。很显然,它们是有很大区别的,运算规则也并不相同。

2.1信息存储

计算机用二进制存储,最小单位是位(bit),但是最有用的还是由八位组成的字节(byte),它是最小的可寻址存储单元,虚拟存储器的每个字节都是由唯一的数字标识,叫做地址。

这一小节主要说明一个对象(或者叫做数据)是如何在存储器存储的,顺便介绍一些和布尔代数有关的概念。

 

十六进制表示法----字----数据大小----寻址和字节顺序----表示字符串----表示代码----布尔代数----位级运算----逻辑运算-----移位运算

为了我们自己方便,我们用十六进制来表示信息。2进制、十进制、十六进制之间的转化。

字是由多个位组成的,它是认整整还有指针的存储单元(最大了),所以字有多大,决定了可以寻址的范围有多大,也就决定了我们可以用多大内存。32位的电脑,可以使用的内存为4G,是因为2^32 = 4 * 2^30 = 4G.

数据大小是有编译器和操作系统决定的。也就是说规定每种类型的变量认是多大的空间。c语言中int a = 10. 那么给a分配4位, double a = 10.0,那么给a分配8位。

当存储占有多个位的数据对象的时候,如何给这个对象安排地址,如何在存储器排列引出了这个问题。寻址是说要访问这个对象,要访问哪个地址,。比如int a = 10.那么a占有了4位,每一位都有地址,比如0x100,0x101,0x102,0x103,可以访问大地址来找到a,也可以访问小地址0x101找到a,认都是从小地址开始。而安排字节顺序就涉及到大端和小端,这是要解决数据对象的高低位和存储器的高低位之间的关系。将数据对象的地位放到存储器的低位,为小端。将数据对象的低位放到存储器对象的高位,为大端。

字符串,相对来说,没有那么复杂了,由一个位存储一个字符,总是从低位到高位存储。

布尔代数对应的是一种运算关系,有 &(与),|(或),~,^(异或)

位级运算是布尔代数的典型应用,运算的时候每一位都按照布尔代数的进行运算。实际当中掩码用的比较多。

逻辑运算,和位级运算不同,他们的结果是ture0x01和false 0x00 && || ! 三种

移位运算,现将一个数转化为二进制,然后按照一定规则运算。

 

2.2 整数表示

在这一小节,我们研究整数这种数据结构在计算机当中是如何表示的。分为两种,无符号型和有符号型。然后研究他们之间是如何进行转换的。同时,当扩充一个数或者截断一个数是如何工作的。其中,在位模式上面基本不太发生变化,但是在计算的数值上面有很大的差别。

 

1整数数据类型----2无符号数的编码----3补码编码----4有符号数和无符号之间的转换----5C语言中的有符号数和无符号数----6扩展一个数字的位表示----7截断数字

1:在c语言当中,有这么几种类型都是表示整数,char, short, int ,long,long long,然后还有他们的unsigned类型,所以一种有10中,在不同的编译器和操作系统中位数可能存在一点差异。

2:我们要区分一下位模式和它的值,位模式是存储在内存的一个个位,而值是我们直观的现实,打印的值。无符号的w位模式为$[x_{w-1},....,x_1,x_0]$ 它的值计算方法B2U = $\sum \limits_{i=0} ^{w-1} x_i 2^i$

3:关于带有符号的数字,我们通常用补码来进行编码。它的值计算方法B2T = $-x_{w-1}2^{w-1}  + \sum \limits_{i=0} ^{w-2} x_i 2^i$。 假如想要将一个数转化为补码,那么可用使用原码 –>反码 –>补码的形式进行转换。

4:有符号数和无符号数在进行转换的时候,位模式是不发生变化的,这一点很重要,只是显示的值发生了变化,对于位模式的解释发生了变化。 B2U- B2T = $x_{w-1}2^w$,所以利用这个公式可以进行两者之间的转换。

T2U(x) = $x + x_{w-1}2^w$,对每种情况进行分析 $T2U = \left\{  \begin{aligned} x &  & x \geq 0 \\ x+2^w &  &x <0 \end{aligned} \right.$ 

反对于另外一种情况U2T =  $u - u_{w-1}2^w$  $T2U = \left\{  \begin{aligned} u &  & u<2^{w-1}\\ 2^w-u &  &u \geq 2^{w-1} \end{aligned} \right.$

5:c语言中,有符号数和无符号数之间运算,会先转换为无符号数,然后进行计算,这一点会导致很多bug,比如0u(表示无符号0) 0u-1 ,我们期望是-1,但是结果为2^32 –1。 会先把-1转化为usigned 为2^32然后相加。

6:无符号扩展是前面直接加0,表示0扩展,而有符号扩展则表示前面的位补上符号位的数,即正数全部写0,负数全部写1。虽然位模式上面发生了变化,但是它们的值是相同的,这点在数学上能够证明。尤其是负数,只要后面相同,前面几个1都是相同的。

7:截断一个数字,在位模式上面表现为直接截断。在计算数值方面,w位,截断为k位,$B2U_k = B2U_w(x) mod 2^k$,即直接模$2^k$计算就可以了。 对于有符号的数字,截断$B2T_k = U2T_k( B2U_w(x) mod 2^k )$,即先把x转化为无符号,然后模$2^k$,最后转化为有符号。

2.3 整数运算

  整数运算在整数表示的基础上进行,进行加减,乘除,乘以常数运算,运算过程涉及到很多的溢出,理解他们是如何工作的。当然,关于整数的运算也涉及到位上是如何运算的,以及转化为我们理解的十进制是如何计算的。下面以运算表示在二进制上面进行的工作,而已计算代表我们在十进制上面自己算的工作。

 

1:无符号加法 –> 2:补码加法–> 3:补码的非-> 4:无符号乘法 –> 5:补码乘法 –> 6:乘以常数–>7:除以2的幂 ->8:关于整数运算最后的思考

1:从二进制的角度来看,相加以后的数字直接截断就可以了。 在运算的角度,就两个数相加,然后模$2^w$,w为二进制多少位。加法会产生溢出,溢出是指,完整的整数结果不能存放到数据类型的字长限制中。

2:补码加法在二进制角度运算,也无符号数加法一样,直接模就行了,符号位也参与这样的计算。所以,两个数很大的时候会产生负溢出,两个数很小的时候会产生正溢出。在十进制上面的计算是这样的:直接相加,模上$2^w$,因为模的关系,转化为无符号的数字,然后将无符号的数字转化为有符号的数字就可以了。

3:补码的非是:定义一个数,这个数和原来的数相加为0。所以,在十进制上运算就是直接取负数,除了$-2^{w-1}$,它的补码的非为本身。在二进制上面运算是这样的:全部位数取补码,然后加1,这样在二进制上面相加全部为0.

4:无符号乘法和它的加法一样简单,十进制上表现为$(x*y)mod 2^w$,二进制书上没有介绍,可能是通过移位加法来实现的。

5:补码乘法,在二进制上面表现的和无符号一样,直接相乘,然后截断就可以了。而在十进制上面,先进行$(x*y)mod 2^w$,得到正数,然后U2T的操作。

6:乘以常数,是以二进制左移的形式来实现的。在书中给出证明,左移k位和乘以$2^k$的效果是一样的。

7:整数的除法所遵循的原则是这样的:向0舍入。比如5/2 = 2.5 向0舍入以后为2。-5/2的结果为-2.5 向0舍入的结果为-2。

      对于无符号数字,除以2的k次幂和右移k次是完全一样的。在位级表现为向右进行k次逻辑右移,右移的结果和向下截断的结果是一样的。对于补码来说,当x为正的情况和无符号数字相同,但是当x为负的情况,右移表示的结果也是向下截断,要比向向0舍入要小1。所以,补码负数采用的原则是 (x+y-1)/y  即右移前,先加上$2^k -1$    x < 0 ? (x + (1 << k)-1) : x >> k。 除以任意的数,不能写作除以2的幂这种情况。

8:在c语言当中,溢出是经常的事情。还有无符号数字和有符号数字一起进行运算,经常导致意想不到的效果

 

2.4 浮点数

  浮点数和整数的表示显然是一个完全不一样的概念。它们使用的策略是不一样的,但是我们人类却对这些数字没有这么敏感。所以,可以看到浮点数是经过精心设计的。

 

1:二进制小数  -> 2:IEEE浮点表示 ->3:数字示例: ->4:舍入 ->5:浮点运算: ->6:c语言的浮点数

1:事实上我们也可以将一个数用二进制小数来表示。将一个数转化为二进制小数的方法是这样的:>0的部分除以2,得到二进制数字。小于0的部分乘以2得到二进制数字,然后拼接在一切就可以了。 二进制小数能够表示诸如$2*n$的数字

2:IEEE巧妙的设计了一套表示浮点数的方法,这是我们平时难以想到的。 总共有三个为S符号位 1位、M尾数 n位,E阶码 k位。最终的数字计算如下:$V = (-1)^S M \dot 2^E$。既可以表示负数,也可以表示正数。 在具体的实现过程当中,分为规格化的和非规格化的两类。 规格化阶码E=e-Bias,M = 1+f  Bias为 $2^{k-1}-1$。e为阶码位计算得到的,f为二进制尾数计算得到的。 非规格化的值 E=1-Bias,M=f。 计算的时候套进去计算就可以了。

3:以数字示例。如何将整数转化为浮点数,首先是先转化为二进制数/小数,然后0后面的为M,用多少次方来计算k。

4:舍入分为4类,向偶数舍入,向零舍入,向下舍入,向上舍入。其中向零舍入以前没有见过,但是它的性质非常的好,在统计值当中均值不变。

5:浮点运算支持结合律,但是不支持交换律。当涉及到(3.14+1e10)-1e10 的时候,因为溢出,所以结果为0.可以参考

关于浮点数的几个有意思的例子

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐