CSAPP:datalab实验报告

文章介绍了C语言中的位操作实验,包括bitAnd、getByte、logicalShift等,以及int到float的类型转换(float_i2f),展示了如何使用位运算符和技巧处理数据的特定位。
摘要由CSDN通过智能技术生成

实验一:bitAnd实验

用~、|实现&操作。

int bitAnd(int x, int y) 
{ 
	return ~(~x|~y);	
}

实验二:getByte实验

取出x中的n号字节,将结果return返回。

int getByte(int x, int n)
{ 
  	return (x>>8*n)&0xFF;
}

注意代码当中0xFF也是默认为32位其他位置默认补零,因此&0xFF和&0x00FF效果相同。本实验的操作是一个典型的操作用于取出一个数据的某几位。

实验三:logicalShift实验

x逻辑右移n位(0<=n<=31) ,将结果return返回。

int logicalShift(int x, int n) 
{
	return ((unsigned int)x)>>n;
}

在C语言当中的位移操作分为逻辑右移和算数右移,对于无符号数来说所有的右移操作都是逻辑右移,而对于有符号数来说所有的右移操作都是算数右移。因此本实验中,现将x转化为无符号数再进行右移以保证对int x,进行逻辑右移的操作。而对于左移操作来说不分逻辑左移和算数左移,都是进行补零操作。

实验九:negate实验

补充函数negate(),计算-x

int negate(int x) 
{ 
	return ~x+1;
}

本实验即计算x的反码,操作就是对于x的每一位都取反再加1。注意要对于补码和反码进行区别对于补码来说,正数的补码是他本身,而负数的补码是他的反码。

实验十:isPositive实验

如果x大于0返回1,否则返回0

int isPositive(int x) 
{
    if (x==0){
        return 0;
    }
	return !(x>>31&1);
}

负数的最高为零,正数的最高位为一,所以只需将x的最高为取出进行判断即可。特别的零分为正零和负零,所以对于零我们需要单独讨论。

实验十一:isLessOrEqual实验

如果x小于等于y则返回1,否则返回0

int isLessOrEqual(int x, int y) 
{
   int t = 1 << 31;
    int xp = !(x & t);//若x为负数则xp=0;正数为1;
    int yp = !(y & t);//若y为负数则yp=0;正数为1;
    int p = x + ~y + 1;//p = x-y
    return (!!(((!xp) & yp) | ((p & t) | !p))) & (!(xp & (!yp)));//后一部分解决当x为正数y为负数的时候返回0;开头部分解决当x为负数y为正数的时候返回1;!P排除了x=y的情况
}

 对于这个题目的代码,我们还有一个比较好理解的版本。

# include <stdio.h>
 int isLessOrEqual(int x, int y) 
{
    if (x==y){
        return 1;
    }
	if (((x+~y+1)>>31)&1==1){
        return 1;
    }
    else {
        return 0;
    }
}
 int main (){
 	int re = isLessOrEqual(5,8);
	 printf ("%d",re); 
 } 

不过这个代码目前存在一些问题,后续可以尝试进行完善。

实验十二:ilog2实验

返回x求以2为底的对数的结果(向下取整)。

由于计算机是以二进制的形式进行存储的,因此计算这种题目对于计算机来说十分简单。因为一个int类型的数再计算机内部为2的不同次幂的连加形式。所以只需找出从高位到低位第一个不为零的数即可。我们可以这样进行书写。

int ilog2(int x) 
{
    if (x<=0){
        return 0;
    }
    else {
        for (int i=30;i>=0;i--){
        if ((x>>i)&1==1){
            return i;
        }
    }
    }
}

实验十四:float_i2f实验

实现由 intfloat 的类型转换。

unsigned float_i2f(int x) 
{
    /********* Begin *********/
    int i = 1;                                                                                                   
    int nega = 0;
    unsigned temp;
    unsigned result;
    if (x & 0x80000000) {//判断x是否为负数,如果是负数则执行nega=1,x=-x
        nega = 1;
        x = ~x + 1;
    }
    if (x == 0) {//判断x是否为零。
        return 0;
    }
    while ((x & 0x80000000) != 0x80000000) {//当x的首位不为1时则继续执行
        ++i;
        x <<= 1;//每次x左移一位
    }//找到x从左到右第一个为1的位数
    result = x << 1;//将x再左移一位即丢弃掉x的第一个为1的位。
    temp = result;//相当于frac位上的内容
    result >>= 9;//再将result右移九位以便填入符号位和exp位
    if (nega) {
        result |= 0x80000000;//将x的符号还原。
    } else {
        result &= 0x7FFFFFFF;//保证x的符号为正
    }
    i = (32 - i) + 127;求出exp
    result = (result & 0x807FFFFF) | (i << 23);把exp位上的内容全部置零把exp填入
    if ((temp & 0x00000100) == 0x00000100) {//舍入步骤
        if (temp & 0x000000FF) {
            return result + 1;
        } else {
            if (result & 1) {
                return result + 1;
            } else {
                return result;
            }
        }
    }
    return result;    
    /********* End *********/    
}

注意对于零需要单独讨论。并且要注意在int类型转化为float类型的数据的时候有时需要进行舍入操作。对于这一过程下图给出了形象的转化过程。

 可以通过视频来了解这一过程进行的详细操作http://【【CSAPP-深入理解计算机系统】2-1.信息的存储(上)】 https://www.bilibili.com/video/BV1tV411U7N3/?share_source=copy_web

 对于舍入操作,对于二进制的舍入,如果舍入到n位,对于n位以后的k位如果>10000....则进一。

如果k位<100000.....则舍去。如果后k位=10000....则对n位进行凑零操作。即如果n位为1则进一,如果n位为0则舍去。

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值