课程实验二

实验题目:填写bits.c文件中尚未完成的各个函数的内容,但是,要求只使用有限数量、规定的操作符。然后通过dlc和btest两个工具来测试代码。

实验目的:本实验为课程实验二,补全bits.c中的15个代码,理解掌握计算机的存储方式和逻辑运算操作。

实验环境:个人电脑、32 位ubuntu18.04环境

实验内容及操作步骤:

第一步填写bits.c文件中尚未完成的各个函数的内容:

1.函数名称:bitAnd()、实现要求:x&y

合法操作:~ |、最大运算符数:8

  【解析】~为位运算,因此得到的&也为位运算,且由德摩根定律,可知:

x∩y=~~x∩y)=~~x~y

  【实现】

2.函数名称:getByte()、实现要求:从x中提取第n个字节

合法操作: ! ~ & ^ | + << >>、最大运算符数: 6

  【解析】先利用n<<3得到n*8,通过x右移n*8,去掉最后的n*8位,

则现在x的最后8位即为想要的结果,再与8位全为1的数(即0xFF)相与,

得到提取的结果。

  【实现】

          

3.函数名称:logicalShift()、实现要求:逻辑位移,x逻辑右移n(0~31)位

合法操作: ! ~ & ^ | + << >>、最大运算符数:20

  【解析】0x7fffffff对应0111 1111 1111 1111 1111 1111 1111 1111,将其

 右移n位再左移1位后,则该数前n位均为0,与x右移n的结果相与即可得到

 x逻辑右移n位的结果(注意,由于最大整数不能超过0xFF,所以用1<<31再取

反来完成实现0x7fffffff的功能)

  【实现】

         

4.函数名称:bitCount()、实现要求:返回x中1的个数

合法操作: ! ~ & ^ | + << >>、最大运算符数:40

  【解析】由于结果不会超过 32,故可以利用一个 32 位二进制数来记录,将每

次的检测位数设定为 4 位的。初始化 tmp=0x1111,用来依次检测 x>>i 的 0,8,

16,24 位是否为 1。利用 val 累加分别计算 4 个字节上 1 的个数, val 的每

个字节的值为对应x 每个字节上的 1 的个数;最后将得到 val 四个字节的值相

加,即 x 四个字节上 1 的个数的和,保留最低字节的信息,为最后结果。  

【实现】

 

5.函数名称: bang()、实现要求:不使用!来计算!x

合法操作: ~ & ^ | + << >>、最大运算符数: 12

  【解析】题目所需要求!0=1,!(0除外其他数)=0;一个数取相反数的规则跟负数

补码规则一样,~x+1,按位取反加 1 即可;一个不为 0 的数原数和相反数相或

的结果符号位必然为 1,为0的原数和相反数相或的结果符号位必然为0;则将符

号位右移31位到最低位取反后与0x01相与则可得到结果。

  【实现】

         

6.函数名称: tmin()、实现要求:求补码编码的最小数

合法操作: ! ~ & ^ | + << >>、最大运算符数:4

  【解析】从补码的公式可以看出当最高位为 1,而其余位为 0 的时候,获得最小值。

  【实现】

         

7.函数名称: fitsBits()、实现要求:求给定的一个数是否能用n位补码表示,

如果可以则返回1

合法操作: ! ~ & ^ | + << >>、最大运算符数:15

  【解析】一个数的前32-n都为0或1则可以用n位补码表示,则可以假设第n-1

  位为符号位,通过先算术左移32-n位再算术右移32-n位后比较与原数是否有差别;如果有差别,与原数亦或后为1,否则为 0,再用逻辑非!,将有差别的返回 0,无差别的返回1;

  【实现】

        

8.函数名称: divpwr2()、实现要求:一个数除以 (2^n),有余数则往靠近0

的方向取舍

合法操作: ! ~ & ^ | + << >>、最大运算符数:15

  【解析】分x为负数和非负数两种情况:当x为非负数时,直接将 x右移n位

即可;当x为负数时,如果x移出的位中不全为零,即有余数,则结果为右移n

位后的结果加 1;

  【实现】

         

9.函数名称: negate()、实现要求:取一个数的相反数

合法操作: ! ~ & ^ | + << >>、最大运算符数:5

  【解析】求相反数,按位取反加一即可。

  【实现】

         

10.函数名称:isPositive()、实现要求:判断一个数是否为正数,是则返回1

合法操作: ! ~ & ^ | + << >>、最大运算符数:8

  【解析】判断一个数是否为正数,看它的符号位即可,但要考虑是否为0,如果

一个数x为 0,则!x =1 ,!!x =0,否则,一个不为 0 的数!x =0 ,!!x =1,

将符号位与!!x相与即可判断是否为正数。

  【实现】

11.函数名称:isLessOrEqual()、实现要求:判断x <= y是否成立,成立返回1

合法操作: ! ~ & ^ | + << >>、最大运算符数:24

  【解析】判断是否有 x<=y,有三种可能情况:第一种,x为负数,y为正数,

即x符号位为1,y符号位为0;第二种,x与y同号,通过判断x-y的大小来判

断正负,只需要判断x-y的符号位;第三种,x等于y,即x^y必为全0,此时取

非得1。

  【实现】

12.函数名称:ilog2()、实现要求: 求一个数的 log2 的值

合法操作: ! ~ & ^ | + << >>、最大运算符数:90

  【解析】求一个数的 log2 的值即为求32位二进制数的最高位1对应l log2

。由x>0,ilog 的结果不会超过 31,则可以用5位二进制来表示。依次折半累

加得出最高位的权,方法如下:

首先判断高16位是否全部为 0,tmp+=2^4*i,x相应右移tmp位;

再判断右移后的高8 位是否全部为 0,tmp+=2^3*i ,x 相应右移 tmp位;

再依次累加得出结果tmp。

  【实现】

13.函数名称:float_neg()

实现要求:将32 位int 型数解读为单精度浮点型数据f,返回-f

合法操作: Any integer/unsigned operations incl,||, &&. also if, while

最大运算符数:10

  【解析】若这个数为特殊值则返回原数;若为非特殊值,则直接对符号位取反。

使用异或操作符^。对1求异或,等价于对1求反;对 0 求异或,等价于保持原

数;当需要对一组数中一部分求反,一部分保持原数时,就可以使用异或运算。

判断一个浮点数是否为特殊值: 截取其阶码位和小数位与阶码位全为1,小数位

全为0,即与0x7f8fffff 比较,若大于它,则必然为特殊值。截取数据,利用与

运算 &,需要截取的数和1与,需要清零的数和0与,即可保留需要的数据部分

  【实现】

 

14.函数名称:float_i2f()、实现要求:将一个整形数转化为浮点数

合法操作: Any integer/unsigned operations incl. ||, &&. also if, while

最大运算符数:30

  【解析】将一个整形数,转化为浮点数,浮点数的符号只取决于第一位,所以

对负数作取绝对值处理之后,所有数都可以按照同一种方法处理;将二进制数左

边的零位全部移出,直到移到“ 1”位为止, 移出的位数 shiftleft 则为 32 位

中前面“ 0”的个数, 因此 32-shiftleft 代表的就是阶码的原码部分, 再加

上 127的移码就可以得到最终的阶码;移完 0 之后得到的 aftershift 这串数,

就是小数部分,所以最后将 aftershift 右移 9位,127+32-shiftleft 左移 23

位,最前面加上符号位,即可得到转移后的数字;

  【实现】

15.函数名称: float_twice()

实现要求:将一个32位int型数解读为单精度浮点型数据f,返回2*f

合法操作: Any integer/unsigned operations incl. ||, &&. also if, while

最大运算符数:30

  【解析】若这个数为特殊值(阶码位全1)则返回原数;若为非特殊值,如果是

规格化数,则对阶码位作+1运算;如果是非规格化数(阶码全为0),则对小数位

作左移运算。符号位不改变。这里涉及到将一个数据拆解为多个部分(符号位、

阶码位和小数位) ,以及最后将各个部分拼合的运算;对于拆分数据,如果只是

保留需要的部分,其它位清零,那么只要作 &运算取数据即可;如果只留下需要

的部分,其它位剔除,那么要先作右移运算,再作类似 &0xFF 的运算截断数据;

对于拼合数据,如果已经将几部分数据处理为置 1 位互不相干(即除了1 有效位

其它位都为 0),那么直接用或 | 运算接合即可;

  【实现】

第二步,利用dlc工具验证代码格式的正确性:

直接/dlc bits.c,代码没有问题,dlc无声返回。

所有最大运算符数均满足实验要求。

第三步,利用btest工具验证代码功能的正确性

1.make btest:

 

2.查看得分,

所获分数41分,15个程序均满足题目对符号和常数的限制要求,正确性证明成功。

3. 输入"./btest [optional cmd line args]"查看bits.c各个功能的实现情况。

4其他操作:

输入"./btest -h"可以查看其它命令的说明。

输入"./ishow <数字>"可以帮助我们进一步理解int的存储。

输入"./fshow <数字>"可以帮助我们进一步理解float的存储。

收获与体会:

通过本次实验,深刻了解了各种数据类型的在计算机中的存储方式,进一步认识了数据的加减乘除、按位取非及!x的实质,更加灵活运用移位操作,会用移位操作来代替数值大的数据,对int转float的操作更加熟练了,提升了编程能力。

同时,在test.c文件中test_fitsBits函数在return前加一行空指令printf("",TMax_n);解决-2147483648不能用二进制表示的问题。

 

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是蒸饺吖~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值