实验题目:课程实验LAB2
实验目的:填写bits.c文件中尚未完成的各个函数的内容
实验环境:个人电脑、linux发行版本。
实验内容及操作步骤:
实验内容:填写bits.c文件中尚未完成的各个函数的内容
操作步骤:
1、bitAnd
根据德摩根律,x&y=((x)|(~y))
2、getByte
因为只要取一个特定的字节,所以可以利用1&x=x、0&x=0的特性,将要取的字节移到最低位,然后和0xff相与,其他的字节会得到0而要取的字节保留。n个字节=8n位,8n位用位运算可表示为n<<3,即x>>(n<<3)
3、logicalShift
因为>>运算符默认是算术右移高位补1,而逻辑右移高位补0,因此可以先进行算术右移,然后把补0替换成1。利用1&x=x、0&x=0的特性,将左边n位位0而右边32-n位为1的数和它相与。
4、bitCount
循环次数等于二进制中1的个数。x&(x-1),每与一次,1的个数减1。
5、bang
求一个数的逻辑非,当且仅当这个数的二进制位全为0时返回1,否则返回0。只有0x00000000和0x80000000的补码是其本身,且只有0x00000000与其补码按位或运算之后最高位是0,其他数都是1。将原码与其补码按位或后右移31位判断最高位,若最高位为0说明原码是0应该返回1,若最高位是1说明原码不是0返回0。而求补码的方式是x按位取反后加1。
6、tmin
返回最小的二进制补码integer,即0x80000000。
7、fitsBits
判断x能否由n位二进制补码表示可看成符号拓展的逆过程,经过x<<(32-n)>>(32-n)后若与原来的x相等,则表示能用n位二进制补码表示x。判断相等可利用异或,相同为0,不同为1,逻辑取反后得到正确映射关系。
8、divpwr2
将一个数x除以2的n次方。若x代表正数,直接右移n位即可,即x/(2n)=x>>n。若x代表负数,除法与右移并不相同,原因是除法是向0取整,而右移位是向负取整,此时x/(2n)=(x+(1<<n)-1)>>n。由于不能用-号,-1可用0表示,即x/(2^n)=(x+(1<<n)+(0))>>n。接下来需要构造一个数使得其在x为正数时等于0,x为负数时等于(1<<n)+(~0)。
9、negate
先按位取反,再加1。
10、isPositive
判断是否大于0。正数的符号位为0,0的符号位也为0。
11、isLessOrEqual
若y>=x则返回1。将y-x(即y+~x+1),当y、x同号时判断y-x符号位即可,当y、x异号时可能会发生溢出,需要看y、x的符号位。
12、ilog2
返回log(x),即求最高位1的索引(0~31)。
13、float_neg
当实参为NaN时(阶码全为1,小数域非零),返回该实参。其他情况更改一下符号位即可。
阶码为第23位到第30位共8位,小数域为第0位到第22位共23位。判断阶码是否全为1:(uf>>23)&0xff0xff,若全为1则结果为0x00;判断小数域是否全为0:!(uf&((1<<23)-1),若全为0则结果为1,否则为0;更改符号位(最高位):uf(1<<31)。
14、float_i2f
将int型转换为float型。int型(二进制表示)可假想小数点在最低有效位右边,(所以肯定是左移了),左移shiftnum-1位,使得小数点移动到第一个有效数字(1)的右边(不代表小数点移动的是shiftnum-1位,这里利用左移使得第一个有效数字1在最高有效位,可以计算小数点移动了32-shiftnum位),那么小数点右边第1位(首位)到第23位就是浮点数表示的尾数部分了,因为这里只要取23位所以存在精度问题,这里采取四舍五入向偶数舍入的方式;阶码部分看小数点移动的位数,加上偏置置(float中为127)即可。即(127+32-shiftnum)<<23。
15、float_twice
计算float类型的uf的两倍。对于非规格化值,使阶码值为1-Bias而不是简单的-Bias是一种从非规格化值平滑转换到规格化值的方法。
实验结果及分析:
收获与体会:
这次实验前面几段代码较易补全,后面几段有一定难度,收获很多。比如4、bitCount,我一开始想的是先计算2位中1的个数,再计算4位中的个数,然后8位、16位、32位,但最终采用的这种循环求解的方式最好,降低了算法的时间复杂度。检测结果时出现报错:bash: ./dlc: 权限不够,和同学交流之后知道可以输入chmod 777 dlc开放权限。