datalab实验全套

终于更新了,本次是准备介绍一下csapp的几个实验。因为这学期刚好有这门课,准备借此机会把这本书系统学习一下。
今天的实验环境配置是根据知乎一个用户https://zhuanlan.zhihu.com/p/339047608
配置的。大概注意以下几点:
1、先下载docker desktop;要配置engine,网上有很多办法,但是要注意几点,首先要确保你的电脑cpu支持虚拟化,默认是不支持的,这个可以在开机bios修改;然后要把windows功能hyper打上勾。这样才可以配置成功。

2.接下来就是linux环境的设置,可以pull一个镜像,安装好一系列的依赖项。
3、最有意思的一步,文件目录挂载。在linux 虚拟环境中添加一个目录,挂载到你自己电脑的某个目录上,没有这个目录会新建。注意两个目录都必须是根目录,你可以写C:/XXXX,D:/XXXX等。
4、注意每次打开需要先启动和进入这个容器。
然后docker start 容器ID启动我们的容器
输入以下命令进入到这个运行中的容器
docker exec -it 容器id /bin/bash
这个id可以利用 docker ps -a获得。

5 make btest编译
./best运行(注意要先cd 到文件的目录中)

接下来就说一下几个题目,都在bit.c文件中。

1int bitXor(int x, int y) {
  return ~(~x&~y)&~(x&y);
}
这个题目主要是用位操作表示异或,涉及到德摩根定律的推理。要推到只有与没有或,这个是需要一点技巧的。
a^b=
1.(a|b)&(~a|~b)
2.~(~a&~b)&~(a&b)
3.(a&~b)|(~a&b)

2.int tmin(void) {

  return 1<<31;

}
让我们写出最小的有符号int ,int32位,1000000....(补码).就是最小的,结果是取反加一,就是2的负32次方

3.int isTmax(int x) {
  return !((~(x + 1) ^ x)) & !!(x + 1);//用异或来判断等于!((~(x+1)^x)) 判断这个是否为1即可判断是否为最大值,最大值x=0111 然后x+1之后就会变成1000 我们对1000 取非 0111 就会重新变回x值,一个例外就是x=-1 由于-1=1111 他利用上面的式子判断也符合。挺难想到的


  }


4 int allOddBits(int x) {
    int a = 0xAA << 8;
    int c = a | 0xAA;
    int d = c << 16 | c;
  return !((x & d) ^ (d)); //求奇数位是否全为1,利用半掩码来算,比较好理解
}

5 int negate(int x) {
  return ~x + 1;//A + ~A = -1 和 A + neg A =0 利用这两个式子我们可以得到 neg A = ~A + 1  
如何获得一个数的相反数,那就是取反加1
}

6 int isAsciiDigit(int x) {
    int lowerBound = 0x30;
    int upperBound = 0x39;
    int sign = 0x1 << 31; //最小值100000....
    return !((x + ~lowerBound + 1) & sign) & !((~x + 1 + upperBound) & sign);   //x-30,39-x必须大于0
}
7 int conditional(int x, int y, int z) {
    int a = !!(x ^ 0x0); //a=0 if x=0 else a =1
    int b = ~a + 1;
    int c = ~(y & ~b) + 1;
    int d = ~(z & b) + 1;
    return y + z + c + d; //如果x != 0 那么 c就会等于0, d=-z, 我们最后就可以返回y 否则我们就返回z
}
int isLessOrEqual(int x, int y) { 
    int a = x >> 31 & 0x1;
    int b = y >> 31 & 0x1;
    int c1 = (a & ~b); //表示 x为- y为+
    int c2 = (~a & b); //表示 x + y -
    int e = y + (~x + 1); // x-y;
    int flag = e >> 31; //如果flag 和 c2 不同则说明了溢出了    x-y会产生溢出
    return c1 | (!c2 & !flag);
}
int logicalNeg(int x) {
    return ((x | (~x + 1)) >> 31) + 1; //如果0,(~x + 1)和x按位或符号位是0,最后结果为1,Tmin和其他数值按位或都为1,-1+1=0
}
int howManyBits(int x) {
    int b16, b8, b4, b2, b1, b0;
    int flag = x >> 31;
    x = (flag & ~x) | (~flag & x); //x为非正数则不变 ,x 为负数 则相当于按位取反
    b16 = !!(x >> 16) << 4; //如果高16位不为0,则我们让b16=16
    x >>= b16; //如果高16位不为0 则我们右移动16位 来看高16位的情况
    //下面过程基本类似
    b8 = !!(x >> 8) << 3;
    x >>= b8;
    b4 = !!(x >> 4) << 2;
    x >>= b4;
    b2 = !!(x >> 2) << 1;
    x >>= b2;
    b1 = !!(x >> 1);
    x >>= b1;
    b0 = x;
    return b0 + b1 + b2 + b4 + b8 + b16 + 1;
}

unsigned floatScale2(unsigned uf) {
    unsigned exp = (uf & 0x7f800000) >> 23; //23-30 这8位
    unsigned sign = uf >> 31 & 0x1;
    unsigned frac = uf & 0x7FFFFF;
    unsigned res;
    if (exp == 0xFF)return uf; //如果exp=255 并且尾数非0 就是NaN 直接return 就好 其次如果frac 全为0 那么则表示无穷大 这两种情况都可以直接return
    else if (exp == 0) {
        frac <<= 1; //如果exp=0 则表示非规格化数 那么我们直接返回uf*2 就可就是把frac>>1
        res = (sign << 31) | (exp << 23) | frac;
    }
    else {
        exp++;
        res = (sign << 31) | (exp << 23) | frac;
    }
    return res;
}

int floatFloat2Int(unsigned uf) {
    unsigned exp = (uf&0x7f800000)>>23;
    int sign=uf>>31&0x1;
    unsigned frac=uf&0x7FFFFF;
    int E=exp-127;
    if(E<0)return 0;
    else if(E >= 31){
        return 0x80000000u;
    }
    else{
​
        frac=frac|1<<23;
        if(E<23) {//需要舍入
            frac>>=(23-E);
        }else{
            frac <<= (E - 23);
        }}
    if (sign)
        return -frac;
    else
        return frac;
}

unsigned floatPower2(int x) {
    if(x>127){
        return 0xFF<<23;
    }
    else if(x<-148)return 0;
    else if(x>=-126){
        int exp = x + 127;
        return (exp << 23);
    } else{
        int t = 148 + x;
        return (1 << t);
    }
}、、从这个题可以看出单精度(32)浮点数能表示的数字的范围

最大值是norm形式,exp为254(再大就是NaN和INF了),frac的每一位全为1(虽然在这题里不是这样),就能得到(2−ϵ)127

最小值是denorm形式,exp为0,frac为1,此时指数e是1-127,尾数额外提供了23位的指数,这样就得到2149

这样直接做就可以了

浮点数这几个题看似很难,其实弄懂它的规则之后还是很好理解的,不像前面有的题很难想到。

可以看到最后结果全对。其中最后一个题目一直时间限制出错,原因是btest.c文件把时间限制在10秒内,改成大一点就可以。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值