整数与浮点数【详解】(一)
1、模运算与阿贝尔群
整数分为无符号数和有符号数。整数在计算机上的运算是模运算,形成的数学结构称为阿贝尔群,阿贝尔群具有以下特点:
①满足运算的交换律和结合律公理
②整数具有单位元——0
③整数具有逆元
由于模运算导致阿贝尔群产生,从而导致了整数与浮点数在运算性质上的极大不同。整数支持加法和乘法的交换律、结合律;而浮点数因为精度的限制,没有交换律和结合律,因此浮点的运算要格外的小心。
下面理解模运算。考虑图1的循环队列,在入队时队尾指针rear=(rear+1)%MaxSize,例如入队前rear指向索引4,那么入队一个新元素后rear=5%5=0。设想如果没有这样模运算rear就将等于5,而5是循环队列中不存在的“溢出数”,规避溢出数的做法就是模运算。在整数结构里,和循环队列对应,整数同样有MaxSize,整数间的运算或是求逆元都可能造成类似循环队列中规避溢出数的现象,因此整数操作采用了同样的模运算。
例如,32bit的数据类型int定义下的算式:
500*400*300*200
>>> -884901888
这个结果很反常,但其本质是模运算规避溢出数的结果。值得注意,对于程序本身,一个数达到了MaxSize,程序就会自认“合理”地采用循环队列的模运算,再从数据大小的起点开始重新计数,这样计算的值就不会超出MaxSize;但是对于操作者而言,即使计算的数确实仍然在该数据类型对应的范围内,但结果已经失去了意义,这种情况下,我们依旧认为出现了溢出(Overflow)。由于程序层面上可以编译通过,所以一般不会造成系统报错;但操作者却要格外小心这类不报错的致命错误。具体的细节和原因接下来阐述。
2、有符号数与无符号数
给出无符号数和有符号数的定义,假设一个
位位向量
=[
,
,……
],则
即二进制转无符号数,其位权均为正。无符号数是二进制的十进制数
即二进制转有符号数,其位权首位为负,其余为正。有符号数是二进制补码的十进制数
可以证明上述的位向量和有符号数、无符号数是一一对应的。一个位向量必由一个无(有)符号数对应,一个无(有)符号数也只对应一个位向量。要注意的是无符号数对应的位向量是二进制数(首位不是符号位),有符号数对应的是二进制补码。
由定义可以直接导出有符号数和无符号数的数值范围
3、加法逆元
从前面知道,模运算导致了阿贝尔群,阿贝尔群的特点是具有逆元。整数的单位元为0,因此整数x加它的逆元应该要等于0
①无符号数的逆元
考虑的是x加多少可以为0,而不是把逆元当作负号对待。如图3(i),从
到
要加
,此时若再加1,由循环队列的模运算就相当于为0,于是无符号数的加法逆元为:
②有符号数的加法逆元
考虑的是x加多少可以为0。如图3(ii),看出正负元素间的轴对称关系,即1~
都有唯一的对称负元素与之对应,因此对于
的情况可以认为逆元就是x的相反数,也就是数学上的意义;对于
的情况由于没有对称元素就要借助最基本的模运算,
从正负两个方向看与0的距离都是
,又考虑到w位的有符号数
,因此不能从正方向加上
这个数,因此采取的方式就是从负方向上减去一个
于是有符号数的加法逆元为:
小结
整数与浮点数系列依然是对CSAPP相关知识点的总结与理解。在下一篇博客里,将继续介绍整数的截断、有符号无符号数转换等知识,如有不足还请指出。