实验内容及操作步骤:

一.代码完善及代码思路说明

/*

* bitAnd - x&y using only ~ and |

*   Example: bitAnd(6, 5) = 4

*   Legal ops: ~ |

*   Max ops: 8

*   Rating: 1

*/

int bitAnd(int x, int y) {

return (~((~x)|(~y)));

}

代码思路:

根据德摩根律,我们可以得出两个数的相与等于其的反相或再取反,即:a&b=~(~a|~b),   取反运算符和相或运算符都已给出因此可用此解法。

/*

* getByte - Extract byte n from word x

*   Bytes numbered from 0 (LSB) to 3 (MSB)

*   Examples: getByte(0x12345678,1) = 0x56

*   Legal ops: ! ~ & ^ | + << >>

*   Max ops: 6

*   Rating: 2

*/

int getByte(int x, int n) {

return ((x>>(n<<3))&0xff);

}

代码思路:

因为我们是要从一个32位二进制的数中截取一个8位二进制的一个字节,因此我    们可以把        想要截取的字节移动到32位二进制的最低八位然后和0xff相与就可以将前24位清 零只        保留最后的八位。至于怎么将想要的8位二进制移动到最后八位,可以利用n的倍数关 系移位将其变为8的不同倍数,然后再对原32位数通过移位操作就能执行。

/*

* logicalShift - shift x to the right by n, using a logical shift

*   Can assume that 0 <= n <= 31

*   Examples: logicalShift(0x87654321,4) = 0x08765432

*   Legal ops: ! ~ & ^ | + << >>

*   Max ops: 20

*   Rating: 3

*/

int logicalShift(int x, int n) {

return ~(((0x1<<31)>>n)<<1)&(x>>n);

}

代码思路:

因为函数传入的x是int型所以在直接用>>进行右移操作时会默认进行算术右移,按符号位进    行拓展,而题目要求我们实现的是逻辑右移。

很自然的可以想到将算术右移后多余的符号位和0相与清零,而要保留的数据部分和1 相与        不变,这样就能实现逻辑右移的操作。

因此对于一个想实现逻辑右移n位的数,我们需要构造一个前n位都是0后面的32-n位都是       1的二进制数来和它相与清除符号位。首先将0x1左移31位得到符号位是1其他位是0的一       个二进制数,因为可用操作符中没有提供减号,所以通过右移n位再左移1位,来实现使这 个二进制数的前n位都是1。然后对这个数取反,就得到了一个前n位都是0后面的32-n位   都是1的二进制数,将它和进行了算术右移的x相与就能清空x前面的n位符号拓展的位, 而保留数据位。实现逻辑右移操作

/*

* bitCount - returns count of number of 1's in word

*   Examples: bitCount(5) = 2, bitCount(7) = 3

*   Legal ops: ! ~ & ^ | + << >>

*   Max ops: 40

*   Rating: 4

*/

int bitCount(int x) {

int tmp=((0x01<<8|0x01)<<8|0x01)<<8|0x01;

int val=x&tmp;

val+=tmp&(x>>1);

val+=tmp&(x>>2);

val+=tmp&(x>>3);

val+=tmp&(x>>4);

val+=tmp&(x>>5);

val+=tmp&(x>>6);

val+=tmp&(x>>7);

val=val+(val>>16);

val=val+(val>>8);

return val&0xff;

}

代码思路:

函数要求出一个int型里一共有几个1,我们可以先构造一个32位二进制        00000001000000010000000100000001,然后让它和x相与就能得到第1,9,17,25位的1的个数,   然后x右移1位就是第2,10,18,26位的1的个数和之前的值相加。这样不断右移最终就能遍历    整个二进制数,这时1的个数分四段保存在32位中,然后折半相加,最终的八位里存储的就        是1的全部数量。

/*

* bang - Compute !x without using !

*   Examples: bang(3) = 0, bang(0) = 1

*   Legal ops: ~ & ^ | + << >>

*   Max ops: 12

*   Rating: 4

*/

int bang(int x) {

return (~((x|(~x+1))>>31))&0x1;

}

代码思路:

函数要求的是实现逻辑运算!,即当一个数为0时返回1,不为0时返回0,因此实际上只需 要判断所给的数是不是等于0即可。

首先想到的应该是x和他自身的关系即和~x相与相或等操作,但是发现并没有什么特例性可        以用来实现这个函数,但是查阅资料发现只有当x为0是他取反加一(~x+1)和x相或后最        高位为0,因为只有x为0时,~x+1为2的32次方会产生溢出,此时x和~x+1的最高符号    位都是0,所以二者相或后也是0。而除了0之外的任何数他们二者符号位相或都是1,可以 利用这个特性。将最高位右移到最低位取反然后和1相与就能实现函数功能。当x为0时返 回1,当x不为0时返回0.

/*

* tmin - return minimum two's complement integer

*   Legal ops: ! ~ & ^ | + << >>

*   Max ops: 4

*   Rating: 1

*/

int tmin(void) {

return (0x1<<31);

}

代码思路:

题目要求的是给出32位2进制补码能表示的最小的整数,根据有符号数的补码的解释规则,        根据定义就能得到,最小的整数的补码表示是10000…0,除了第一位符号位是1,后31位全       为0,因此直接将0x1左移31位得到。

/*

* fitsBits - return 1 if x can be represented as an

*  n-bit, two's complement integer.

*   1 <= n <= 32

*   Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1

*   Legal ops: ! ~ & ^ | + << >>

*   Max ops: 15

*   Rating: 2

*/

int fitsBits(int x, int n) {

int tmp = x >> (n+(~0x1+1));

return ( !tmp | !(tmp+1)  );

}

代码思路:

经过多组的数据测试,我们发现对于一个正数如果想要被n位的二进制准确表示,那么他的        32位二进制表示从第n位到第32位都应该是0,因为截取后第n位就是其符号位,同理,对      于一个负数他的32位二进制表示从第n位到第32位都应该是1,这样的数才能被准确表示。

因此我们只需要把一个数x的32位形式右移n-1位,只保留第n到第32位如果全为0或1    就能被准确表示,反之不能。

因为可用操作符中没有给出减号 ,所以用0x得到补码形式的-1 和n相加得到n-1,然后通  过表达式(!tmp | !(tmp+1))可以判断前面的字符是否为全0或全1,如果不是返回0,是的话      返回1

/*

* divpwr2 - Compute x/(2^n), for 0 <= n <= 30

*  Round toward zero

*   Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2

*   Legal ops: ! ~ & ^ | + << >>

*   Max ops: 15

*   Rating: 2

*/

int divpwr2(int x, int n) {

int sign = (x>>31);

int temp = (0x1<

return (x+(sign&temp))>>n;

}

代码思路:

这个函数要实现的就是二进制的除法,二进制除以2的幂,我们在课本中已经学到过,二进        制除以2的幂可以通过右移来实现,但是对于有符号数,正数和负数的算法是不同的的,直        接右移进行的是向下取整,而我们要的是向0取整,因此在对负数的计算是需要加一个偏量 2^n-1。

算法设计,首先我们可以先判断x是否为正数,把x算术右移31位把他的符号位拓展32位,

偏量2^n-1可以直接用1左移然后和0的取反相加得到,将这两个数相与当x为正数时,符号    位全是0,相与为0则不加偏量,当为负数时,符号全为0,和偏量相与得到的还是偏量加给 x,然后再进行右移操作得到的商就都是向零取整的了。

/*

* negate - return -x

*   Example: negate(1) = -1.

*   Legal ops: ! ~ & ^ | + << >>

*   Max ops: 5

*   Rating: 2

*/

int negate(int x) {

return ((~x)+1);

}

代码思路:

这个题是求相反数的补码表示法,是在数据的补码表示中学过的知识点,我们可以用取反加        一的方法得到一个数相反数的补码表示。

/*

* isPositive - return 1 if x > 0, return 0 otherwise

*   Example: isPositive(-1) = 0.

*   Legal ops: ! ~ & ^ | + << >>

*   Max ops: 8

*   Rating: 3

*/

int isPositive(int x) {

int  temp=x>>31;

return !( temp | !x );

}

代码思路:

函数要求判断一个数x是否为正数,如果不是则返回0,因此当x为负数或者是0的情况就返 回0,我们可以通过符号位判断正负将x算术右移31位得到32位的符号位,通过!x来判断      x是不是0,当符号位是1或者说!x是1,即x是负数或者是0的时候返回0.实现函数。其  他时候也就是大于零的时候返回1.

/*

* isLessOrEqual - if x <= y  then return 1, else return 0

*   Example: isLessOrEqual(4,5) = 1.

*   Legal ops: ! ~ & ^ | + << >>

*   Max ops: 24

*   Rating: 3

*/

int isLessOrEqual(int x, int y) {

int signx = (x >> 31) &0x1;

int signy = (y >> 31) &0x1;

int isSameSign= ! (signx ^ signy) ;

int p=! ( ( (~x)+1+y ) >> 31);

int ans = ( isSameSign & p ) | ( ( !isSameSign ) & signx);

return ans ;

}

代码思路:

很容易想到通过判断y-x >= 0来判断x和y的大小关系,但是这样就会出现y-x溢出的情况,     为了防止这种情况发生,我们可以将这个问题分为同号和异号两种情况。同号:我们就通过        判断y-x的符号是不是=0的情况! ( ( (~x)+1+y ) >> 31)。如果是异号:我们就直接判断x的符        号是不是-即可。这样就能避免溢出而出现的不准确的错误。

/*

* ilog2 - return floor(log base 2 of x), where x > 0

*   Example: ilog2(16) = 4

*   Legal ops: ! ~ & ^ | + << >>

*   Max ops: 90

*   Rating: 4

*/

int ilog2(int x) {

int count = 0;

count = (!!(x>>16)) << 4;

count =count+((!!(x>>(8 + count)))<<3);

count =count+((!!(x>>(4 + count)))<<2);

count =count+((!!(x>>(2 + count)))<<1);

count =count+((!!(x>>(1 + count)))<<0);

return count;

}

代码思想:

这个函数的补全方法是利用二分的思想,根据公式log(x)=16a+8b+4c+2d+e。那么   count=abcde就是log(x)的二进制表示。因为x长32位,首先我们先将x>>16,  判断高16       位是不是大于0,如果>0,!(x>>16)就是0,我们要将他转换到a的位置就是将! !(x>>16)再次        取非得到1,然后<<4,到a的位置,它的权是16,就说明这个数大于16,1肯定在高16位   处,然后在接着将高位折半到8位,就是>>(8+16),看看高8位是不是也是>0。这样一步步    的分下去就是答案。最终得到的count就是log(x)。

/*

* float_neg - Return bit-level equivalent of expression -f for

*   floating point argument f.

*   Both the argument and result are passed as unsigned int's, but

*   they are to be interpreted as the bit-level representations of

*   single-precision floating point values.

*   When argument is NaN, return argument.

*   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while

*   Max ops: 10

*   Rating: 2

*/

unsigned float_neg(unsigned uf) {

unsigned x=0x80000000;

unsigned wu=0xFF000000;

unsigned tmp = uf<<1;

if( (wu&tmp ) ==  wu)

{

if(tmp != wu) return uf;

}

return uf^x;

}

代码思路:

函数要实现的功能就是返回输入的uf的负数形式-uf。如果uf是NAN形式就直接返回参数。        由ieee浮点数的编码规则可知,浮点数是由s符号位(1位)E阶码(8位)M尾数(23位)(-1)^s * M   * 2^E       组成的,当E是0xFF时,要么这个数是inf或NAN,可inf也很特殊就是M就是 全0的情况所以我们捉住这个特殊点,先把uf<<1忽略了s符号位,就看看0xFF000000在      uf<<1的位置是不是也是0xFF000000,如果是再判断一下uf是不是就等于0xFF000000就    代表他原先就是个inf数,如果不等于0xFF000000就代表他原先就是个NAN数。按情况和    0x80000000异或就可以实现符号位反转。

/*

* float_i2f - Return bit-level equivalent of expression (float) x

*   Result is returned as unsigned int, but

*   it is to be interpreted as the bit-level representation of a

*   single-precision floating point values.

*   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while

*   Max ops: 30

*   Rating: 4

*/

unsigned float_i2f(int x) {

unsigned sign=0,shiftleft=0,flag=0,tmp;

unsigned absx=x;

if( x==0 ) return 0;

if( x<0 ){

sign=0x80000000;

absx=-x;

}

while(1){

tmp=absx;

absx<<=1;

shiftleft++;

if( tmp&0x80000000 ) break;

}

if( (absx & 0x01ff) > 0x0100 ) flag=1;

if( (absx & 0x03ff) == 0x0300 ) flag=1;

return sign+(absx>>9)+((159-shiftleft)<<23)+flag;

}

代码思路:

题目要求是把一个int型转化成float型表示,首先要用一个符号位储存符号,因为int的正负      数表示方法和float不同,所以先把负数从补码形式转化成方便float表达的形式,然后获取到       最高位的1,和阶码,这其中需要注意的就是在保留23位的时候需要进行向偶数舍入考虑是  否进位,最后把几个部分相加就能得到转化成的float型。感觉这道题目比较难。

/*

* float_twice - Return bit-level equivalent of expression 2*f for

*   floating point argument f.

*   Both the argument and result are passed as unsigned int's, but

*   they are to be interpreted as the bit-level representation of

*   single-precision floating point values.

*   When argument is NaN, return argument

*   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while

*   Max ops: 30

*   Rating: 4

*/

unsigned float_twice(unsigned uf) {

int s = uf & 0x80000000;

int e = uf & 0x7f800000;

int m = uf & 0x007fffff;

int ans = 0;

if (e == 0x7f800000) return uf;

if (e == 0) ans = s | (uf << 1);

else  ans = s + e + 0x00800000 + m;

return ans;

}

代码思路:

本函数要求实现的的是浮点数乘2,对其进行处理我们可以先把浮点数拆成s(1位)E(8位)M(23       位)三个部分,首先,考虑特殊值的情况,不管是NAN还是无穷的情况返回的值都是他本身,      所以只要阶码部分全为1,就返回参数本身。对于非规格化数:我们只需要将其整体左移一位        并和符号位相或就可以。对于规格化数乘2也就是阶码加一,将阶码加一后再把整个数组合        起来就可以了。

实验结果及分析:

对补充完整后的代码进行检查,符合要求,代码合法:

对结果进行检验,所有样例均通过:

收获与体会:

通过本次实验,感觉这次实验对我们对数据的存储和表达方式的要求比较高,   有很多题都比较难,很难想到,尤其是后面对浮点数进行操作的几个函数,必须 十分灵活的运用移位操作,熟悉位之间的转换。

这次实验不仅要求我们掌握好知识点,还要求我们的思路必须打开,要能灵活   的应用,真正从底层上加深了对数据的存储和表示的理解,虽然有些函数自己真 的很难写出来,只有在参考了网上的资料后才能写得出来。但是相信经过了这次 实验,对于数据表示和存储能有更深的理解。

标签:tmp,右移,return,ops,--,32,int,实验,ICS

来源: https://blog.csdn.net/weixin_44668030/article/details/110492017

ics计算机系统全称,ICS计算机系统实验--datalab实验相关推荐

  1. 计算机系统实验--DataLab

    实验题目:Lab2–Datalab 实验目的: 修改bits.c文件,完善bits.c中的函数,使它在不违反任何编码准则的情况下通过所有btest测试. 实验环境: 虚拟机:VMware WorkSt ...

  2. 【计算机系统基础bomb lab】CSAPP实验:Bomb Lab

    [计算机系统基础bomb lab]CSAPP实验:Bomb Lab CSAPP 实验:Bomb Lab 实验内容简述 实验环境 实验过程:phase 1 phase 1 调试过程 实验过程:phase ...

  3. 计算机网络概念初探-计算机网络实验教程-实验一

    计算机网络概念初探-计算机网络实验教程-实验一 Computer Science Class1 GuoYiXuan 2021/12/25 计算机网络学习笔记系列 计算机网络实验教程-实验一:计算机网络 ...

  4. 计算机网络实验设计应用题,计算机网络实验三实验报告.doc

    计算机网络实验三实验报告 实验综合成绩 (百分制) 实验评阅教师签名其中实验态度优良中及格不及格实验报告优良中及格不及格 实 验 报 告 实验时间: 2015年 12 月 24日 实验运行环境 win ...

  5. 电力电子技术课程实验:实验二、可控整流电路及pwm逆变电路设计、制作、测试

    电力电子技术课程实验:实验二.可控整流电路及pwm逆变电路设计.制作.测试 第一部分.可控整流电路预习报告 一.知识准备 1.1.三相桥式全控整流电路的构成及其工作原理 1.2.三相桥式全控整流电路对 ...

  6. 计算机网络应用层协议实验,计算机网络实验报告--应用层协议.doc

    计算机网络实验报告--应用层协议 附件1 中北大学经济与管理学院 实验报告 课程名称 计算机网络 学号 1409044119 学生姓名 辅导教师 段庆峰 系别信息管理与信息系统实验室名称实验时间1.实 ...

  7. 周信东c语言实验二实验报告,周信东主编最新版C语言程序设计基础实验一实验报告.doc...

    周信东主编最新版C语言程序设计基础实验一实验报告.doc 下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览.不比对内容而直接下载带来的问题本站不予受理. 2.下载的文档,不会出现我 ...

  8. c语言实验七实验报告,C语言实验七 数 实验报告.doc

    C语言实验七 数 实验报告 C语言程序设计 实 验 报 告 实验题目 实验七 函数 实验目的 掌握函数定义的方法: 掌握函数实参与形参的对应关系,以及值传递的方式. 掌握函数的嵌套调用和递归调用的方法 ...

  9. 上海大学matlab实验报告,实验中心

    自动化系实验中心介绍 一.基本情况 自动化系实验中心负责自动化系本科实验课程教学工作,现有专业实验室9个,面积共计790平方米,承担基础实验.专业实验等实验课程共11门(其中上海市精品实验课程1门). ...

  10. 计算机网络数据分析报告,贵州大学计算机网络实验报告-实验四-分析IP协议数据包格式...

    贵州大学计算机网络实验报告-实验四-分析IP协议数据包格式 (7页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 贵州大学GUIZHOU UN ...

最新文章

  1. [UE4]C++实现动态加载的问题
  2. Hibernate4继承映射
  3. QT 调用wmi 异常报错 内存异常等
  4. 北斗导航 | GPS原理与接收机设计——青冥剑(金码、C/A码、P码)
  5. boost::tti模块测试函数模板
  6. 介绍一下 information_schema 库
  7. (七)立体标定与立体校正 【计算机视觉学习笔记--双目视觉几何框架系列】
  8. IPython系统相关内容及其配置信息
  9. 《中国人工智能学会通讯》——7.7 结束语
  10. node.js连接数据库得基本操作
  11. java rxtx串口读写_Win7环境下Java串口数据读写(RXTX)
  12. 那些年Android开发遇到的坑(JNI 之 Illegal start byte 0xfe)
  13. 关于打造超级产品,初创型企业如何找到巨头的“阿喀琉斯之踵”?
  14. Matlab中median函数的使用
  15. WEBOS——第一次感觉云计算离我们如此之今
  16. 多台计算机直接连接打印机,多台电脑如何连接打印机?
  17. 想把静态网页放到服务器上,怎么样让所有人都去访问到
  18. Android 自定义view完全解析--带你通透了解自定义view
  19. (3)riak_core系统的工作方式
  20. C语言入门(九)>>>循环 - while循环

热门文章

  1. js获取文件的后缀名
  2. Linux GCC make文件的写法4--清晰版
  3. wordpress让百度分享支持https
  4. 宝塔控制面板如何添加伪静态
  5. wordpress如何获得当前用户的头像
  6. 深职院c语言考试试卷,深职院第1章C语言基础与入门教学.ppt
  7. 为什么.class文件查看不了_恕我直言,这可能是你见过最详细的class文件结构分析
  8. python调用c++动态库_python调用c++开发的动态库
  9. win7工作组无法查看计算机名,win7系统无法查看工作组计算机怎么解决
  10. 大数据要学javaweb吗_学习大数据需要学习javaee的内容吗?