Data Lab 2(深入理解计算机系统)

记录自己的学习过程

int conditional(int x, int y, int z)

功能:实现与三目运算符表达式 x ? y : z 具有等价功能的函数
主要是模仿三目运算符的逻辑

int conditional(int x, int y, int z) {
    //x不为0时结果为y,为0时结果为z.
  int test1,test2,test3;
  test1=(!!x);
  test1=(test1<<31)>>31; //获得!!x的值填充32位。
  test2=!x;
  test2=(test2<<31)>>31; //获得!x的值填充32位。

  test3=(test1&y)+(test2&z); //分别和y,z进行与运算即可得出结果。
  return test3;
}

int isNonNegative(int x)

功能:当 x >=0 时,返回1;否则返回0
判断符号位即可

int isNonNegative(int x) {
    //判断x的符号位
  int test1=x>>31;//为0xFFFFFFFF则要return0,为0x00000000要return1.
  test1=!test1; //使用!将其变为0与1.
  return test1;
}

int isGreater(int x, int y)

功能:当 x > y 时,返回1,否则返回0
可能有溢出的情况,所以将x和y分为同号和异号两种情况进行考虑
正 - 正 ——不会溢出,返回x-y-1符号位的取反即可(减1是为了排除相等的情况)
正 - 负 —— 函数必须 return 1
负 - 正 —— 函数必须 return 0,可以看到,异号状态返回值为y的符号位。
负 - 负——不会溢出,返回x-y-1符号位的取反即可(同理)

int isGreater(int x, int y) {
    //需要判断x与y同号和x与y异号的情况。
 int equalval=x^y;        //判断x与y相等及符号位是否相同。
 int subval=x+(~(y+1)+1); //计算x-y-1;
 int result=(((~subval)&(~equalval))+(y&equalval))>>31;//分别计算同号与异号的情况。
                                                  //并取符号位。前一个为同号,后一个为异号
 result=result&0x01;
 return result;
}

int absVal(int x)

功能:计算x的绝对值
同样也是分为x为正和负两种情况考虑
若x为正数,则直接返回x
若x为负数,则返回~x+1

int absVal(int x) {
    //x为正则返回x, x为负,则返回~x+1;
  int result,signbit;
  signbit=x>>31;//获得signbit扩充到32位的01序列,为00...00(x为正数) 或 11...11(x为负数)
  result=((~signbit)&x)+(signbit&(~x+1));//利用符号位计算结果。
                                        //若x为正数,则后半段为0,前半段为x
                                        //若x为负数,则前半段为0,后半段为~x+1
  return result;
}

int isPower2(int x)

功能:判断x是否恰好等于 2^n,如果等于则返回1,否则返回0
考查2^n的位的性质
若 x为 2^n,则 x&(x-1)=0
假设 x为 2^5, 则 x=100000,x-1=011111。显然 x&(x-1)=0

但还需排除负数(即只有符号位为1的情况)和 0 的干扰
等价于判断 x>0
和上一个isGreater 函数方法类似,需要考虑 x<0时溢出的情况,所以分为x>=0和x<0两种情况

int isPower2(int x) {
    //首先2的幂有x&(x-1)为0的特征,然后只要判断x大于0(和isGreater判断方法一致)
  int signbit=(x>>31)&0x01;
  int signbit2=((x+~0x00)>>31)&0x01;
  int abzero=signbit+(signbit2&(~signbit));//判断是否大于0,大于0为0,否则为1
  int nature=x&(x+~0x00);       //性质符合为0
  int result=abzero+nature;//两者都满足的情况下为0,其他情况都不为0.
  return !result;
}

unsigned float_neg(unsigned uf)

功能:求浮点数f的相反数
说明:参数uf为浮点数f为在计算机中的二进制编码所对应的无符号数。返回值为浮点数f在计算机中的 二进编码所对应的无符号数。
合法的运算符:全部有符号数和无符号数的运算符、||、&&、if 和 while
注意:如果输入为NaN,则返回值等于uf
可使用的运算符数:10
难度:2

如题目要求,分为NaN情况和一般情况
NaN情况 :判断出来后,直接返回 uf 的值
NaN:即阶码位全为1,小数位不全为 0时为NaN
一般情况:根据 IEEE 754 原则,将 float 阶码位 ^ 1, 然后返回

unsigned float_neg(unsigned uf) {
    //分为NAN和规范数两种情况。
  unsigned result;
  int elsign=uf&0x7fffffff;    //排除符号位影响。
  int exp=elsign>>23;          //获得阶码位
  if((!(exp^0xff))&&(elsign^0x7f800000))//前一个判断阶码位是否全为1
                                        //后一个在前一个基础上判断小数字段是否不全为0
  return uf;
  result=uf^0x80000000;
    return result;
}

unsigned float_i2f(int x)

功能:返回浮点数(float)x在计算机中的二进制编码所对应的无符号数
即把 x 转换为 浮点数类型对应的无符号数字
就是把(float)x的位表示放在一个无符号变量中返回

根据IEEE 754原则和向偶取整原则一步一步进行实现

IEEE 754 中 float x=(-1)^signbit * 2^(exp-Bias)(1+frac)
例:float f=15213.0 ,其二进制值为0011 1011 0110 1101. 在IEEE 754中
其位表示为:(-1)^0 * (1.1101101101101) * 2^13
exp=13+bias(在float中为127)=1000 1100(二进制)
frac=1101101101101…0(小数去掉1,共23位)
s=0

向偶舍入:(四舍六入五成双)
即规定的位后面>100,则进1
若<100,则舍去
若等于100,若此位为1,则进1;此位为0,则舍去。

unsigned float_i2f(int x) {
    //即将x变为float型。按照IEEE和向偶取整的规则即可。
  int signbit,highbit,exp,fracbits,flag;
  unsigned temp,result;
  if(!x)
  return x;             //由于规范数情况不包含0,所以先处理0情况。
  signbit=(x>>31)&0x01;
  if(signbit)
  x=~x+1;              //获得符号位,并将x变为正值。
   highbit=0;
  temp=x;
  while(!(temp&0x80000000))
  {
     temp<<=1;
     highbit++;
  }                    //获得x的最高有效位,即确定fraction的位数。
  temp=temp<<1;
  exp=127+31-highbit;  //根据单精度浮点数规则计算出exp,和fraction位数。
  fracbits=31-highbit;
  flag=0;               //进行向偶舍入
  if((temp&0x1ff)>0x100)
  flag=1;              //出现在规定位置后大于0b100的情况就进1.
  if((temp&0x3ff)==0x300)
  flag=1;              //出现最后一位为1,且下一位为1的情况也进1(向偶取整)
  result=(signbit<<31)+(exp<<23)+(temp>>9)+flag;//计算最终结果
  return result;
}
  • 35
    点赞
  • 93
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
### 回答1: 好的,这里是您要求的回答: 这个问题涉及到计算机系统的实验课程——深入理解计算机系统(CS:APP)的第一个lab任务,也称为Data Lab。这个任务要求学生使用C语言编写函来实现不同的位级操作,从而深入理解计算机字的存储和运算。 ### 回答2: 在Data Lab的第二部分,我们学习了如何用不超过十六个操作来实现不同的位运算。这些操作包括移位,逻辑运算,比较和掩码等。通过这些操作的实现,我们可以进一步理解底层计算机系统位运算的实现原理。 在实现这些操作时,我们需要了解底层计算机系统的运算和据类型。如符号扩展、零扩展和反码等。同时,在编写代码时需要熟练使用位运算的操作符号以及一些基本控制流语句如循环、条件语句等。 除了实现这些基本操作,我们也需要应用这些操作来解决一些实际问题。例如,实现一个函,将一个十六进制按位翻转,或是计算一个整二进制表示1的量等。 通过Data Lab的学习,我们深入了解了计算机系统底层的位运算实现原理,并学会了如何用简洁高效的代码实现这些操作。同时,这些操作也常常被用在各种领域的计算机编程,对于未来的学习与工作都有很大的帮助。 ### 回答3: 在《深入理解计算机系统lab1:data lab(二),我们主要学习了位运算和两个的补码表示。这些知识对于我们了解计算机的原理和编码方式非常重要。 在这个实验,我们需要完成一些与位运算相关的任务。其包括: 1. 实现位运算。我们需要用 C 语言实现一些常见的位运算,如与、或、非、异或、左移、右移等。 2. 计算 x 的相反。 3. 检查 x 是否为零。 4. 判断 x 的符号是否为负。 5. 计算 x 和 y 的和,但不能使用加法运算。 为了完成这些任务,我们需要对 C 语言据类型的细节和位运算的机器级实现有一定的了解。例如,我们要了解有符号整无符号的区别,以及它们在机器上的表示方式。我们还需要理解位运算的计算过程,包括位移的规则、符号扩展和逻辑运算等。 通过这个实验,我们可以更深入地理解计算机的工作原理,学会用底层的方式实现高级的运算,掌握常用的位运算技巧。这对于提高编程的效率和代码的可读性都有很大帮助。同时,这也为后续的计算机科学学习打下了坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值