首页 > 代码库 > CSAPP深入理解计算机系统第二章荟萃
CSAPP深入理解计算机系统第二章荟萃
1、可以利用数字的算数右移,然后利用0XFF这样的数字做掩码运算,可以获取到一个数字的符号位。计算机的移位运算有一种很重要的作用就是利用掩码运算去提取一个位模式的一段信息。
2、在C语言中的条件语句,以及三目的条件运算符,都可以用移位的方式来做。
3、在进行位扩展操作的时候,比较讲一个32位的有符号数扩展到64位,那么在保证原来的值不变的情况下,把31个低位扩展到64位的低位上,而最高的符号位扩展到高33位上。
4、利用位模式仅仅只能表示一些2的n次幂的一些浮点数,其他的比较特殊的有理数,会近似表示
5、因为使用了标准的浮点数形式,所以在存储浮点数位数的时候,都不会存储浮点数的整数部分,因为我们都已经规定了浮点数的整数部分是1,所以就没有必要存储,只存下小数点后面的尾数即可。
6、浮点数规格化的值,也就是标准形式我们已经知道是什么情况了,那么在运算的过程当中,出现一些特殊的值,或者说是错误的值我们怎么处理呢。
0.0 此时OS会把符号位,尾数,阶码全都变为0
当阶码都为1的时候,如果尾数全为0,那么我们就要看符号位,如果符号位为1,那么就是负无穷。如果符号位为0那么就是正无穷。
当尾数不是0的时候,那么他就不是一个有效的数字,用NaN来代替,思议就是not a number。这个值也很有用,用于一些非法的计算结果,比如对-1开方。
7、因为在浮点数的补码里面,全为0或者全为1的时候表示的是一些特殊值,所以在表述整场浮点数值的时候就不能用这些,所以为了弥补这些误差,用了一个偏差值Bias.利用exp(阶码的位表示) - Bias获取真正的浮点数的阶码值。
Bias的范围是1-2^(k-1) - 1, k就是阶码的尾数,阶码尾数应该因为机器的关系也是固定的。
之所以加入了一个Bias,一开始看书的时候我没看懂,后来看视频的时候我才明白,因为无论是在单精度还是在双精度的数值中,你的指数是应该能够表示负数的,因为阶码存储在符号位和尾数的中间,所以阶码是一个无符号数,如果是单精度的话,阶码一共有8位,那么所能表示的值就是1---254,这样的话,为了能够表示负的指数,就要减掉Bias,这样就能够表示-126~127的范围的指数。
将浮点数规格化的步骤:
(1)将一个浮点数变为二进制,并且写成1.x的科学记数法形式,注意是2进制,基数是2.这样的话,小数点后面的就是尾数部分,可以在尾数部分后面补足0,如果是单精度的话,要保证尾数的一个23位。
(2)因为在计算阶码的时候会用到E = exp - Bias, 所以exp = E+ Bias。这里我要强调的是,我们在写数字的时候,所看的那个阶码就是E,比如1.00000*2^12,,那么此时12是E不是exp这个位模式所代表的值。
(3)最后把对应的三个位置上的位模式写入对应的位置即可。
浮点数的运算:
(浮点数的表示不像是整数,整数是能够表示确切值的,但是浮点数却不能,它是有可能做一些四舍五入的操作的,所以只是编码,不能代表准确值,因为尾数和阶码等等都是有精度限制的,有些我们能够手写出来的浮点数,但是计算机并不一定能够表示出来。)
在浮点数运算的时候,可能会出现这样两个问题,一个是加法的时候,两个数的阶码不同,这样就要调整尾数,以便两个数的小数点能够对齐,这样才能够相加。
第二个问题是乘法的时候,由于乘法的时候两个数的指数可能都很大,这样的话很可能就会溢出。所以,这个时候人们想出了一个办法,就是先不管溢出其他别的问题,首先计算出运算准确的结果,然后在进行舍入操作,使得结果能够控制在规定的精度内。
(a)舍入操作的种类:1.向0舍入 2.无限向负无穷舍入 3.无限向正无穷舍入 4.向最近的舍入(貌似看起来是最好的办法,但是一个数在两个整数中间的时候,这种情况会出问题)5.向偶数舍入
(b)但是要注意的是,在进行带有舍入操作的运算的时候,是不能运用结合律还有分配律的。这两个数学运算定律在带有舍入操作的浮点数运算里是不适用的。
(3.14 + 1e10) - 1e10 != 3.14 + (1e10 - 1e10) 1e20 * (1e20 - 1e20) != (1e20 * 1e20) - (1e20 * 1e20)
默认的情况下,浮点数的舍入方式是向偶数舍入。
浮点数在C语言:
第一个要点也是我很熟悉的,以前在打ACM比赛的时候老师经常强调的一点就是不要用==符号去比较浮点数,那样会出问题。事实上很多数学函数以及运算符用在浮点数上都会出现问题,所以还是要慎重的好。最好的判断两个浮点数是否相等的办法就是使用减法,如果两者的结果是一个非常非常小的量,那么就可以近似的认为这两个浮点数是相等 的。
浮点数和整数之间的转化:
从int ---> float可能会发生舍入,但是不会发生溢出
从int --> double,如果Int的值是在53位以下的(包括53位),会得到一个精确的转换。
从float --> double, 我们会得到一个精确的转换因为double的精度远远大于float的精度
从float, double -- > int,这样的转化可能会有问题,一个是从单精度浮点数到Int,由于阶码的存在,要调整尾数的尾数,所以在移位操作的时候可能会丢掉一些低有效位。并且这样的转化会按照向0舍入的操作去进行处理数据。另一个问题是浮点数可能会远远大于或者小于整型能够表示范围,因此我们把两种类型的浮点数的比整型最小值还要小的变为Tmin,并且一些在浮点数中特殊的值,我们会将它们都转化为Tmin或者Tmax。
浮点数的表示基本有一下几种方式: