首页 > 技术文章 > 深度懵逼计算机系统。。。DataLab。。

cww97 原文

折腾系统折腾了一星期。。。电脑变板砖无数次
昨晚立了个flag,要一晚写完这个实验题。。。。
//秋雨上次给我推荐了李宗盛的给自己的歌,
//一边听一边写写了一晚上。。。
写完发现,,,编译命令抽风,,,死活不给编译

这里写图片描述

睡一觉,把elearning上面的实验代码重新下载一遍
然后把自己写的再填进去,,,编译能用了
估计是自己写的时候乱改,,,把btest给玩坏了

编译用./dlc一出来30个error。。。尼玛,不合法,again
这里写图片描述
评测机还是比较良心的,给了WA的数据
这里写图片描述
终于过了
同学们加油,祝你们好运
下面贴的代码我把前面一大段废话给扔掉了,全是forbidden= =

/* 
 * CS:APP Data Lab 
 * 
 * <陈伟文 10152510217>
 *
 *================2016.3.27=13:29==================
 *
 * bits.c - Source file with your solutions to the Lab.
 *          This is the file you will hand in to your instructor.
 *
 * WARNING: Do not include the <stdio.h> header; it confuses the dlc
 * compiler. You can still use printf for debugging without including
 * <stdio.h>, although you might get a compiler warning. In general,
 * it's not good practice to ignore compiler warnings, but in this
 * case it's OK.  
 */

/* 
 * 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);
}//return x&y 
/* 
 * 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;
}
/* 
 * 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 x>>n 负数会挂
    int t=(1<<31)&x;//取符号位 
    t=((t>>n)<<1); 
    t=~t; //符号位前一位清0 
    return (x>>n)&t;
}
/*
 * 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) {//统计一个数有多少个二进制1 
    //http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel 
    //没怎么懂原理,弄了几个数据手动模拟了一下,,
    //刚开始的x可以理解为每一位二进制下有多少个1(非0即1) 
    //然后每一步大概就是合并两段的1的个数 
    //最后全堆到前16位 
    //x=(x+(x>> 1))&(0x55555555);// 01010101 01010101 01010101 01010101
    //x=(x+(x>> 2))&(0x33333333);// 00110011 00110011 00110011 00110011 
    //x=(x+(x>> 4))&(0x0f0f0f0f);// 00001111 00001111 00001111 00001111 
    //x=(x+(x>> 8))&(0x00ff00ff);// 00000000 11111111 00000000 11111111 
    //x=(x+(x>>16))&(0x0000ffff);// 00000000 00000000 11111111 11111111
    //如果有神犇能看懂请教我  
    //fuck,.,,,,Illegal constant   (only 0x0 - 0xff allowed)
    int tmp=(((0x01<<8|0x01)<<8|0x01)<<8|0x01)<<8|0x01;
    int val=tmp&x;//检测 x 的 0,8,16,24 位是否为 1
    val+=tmp&(x>>1);//检测 x 的 1,9,17,25 位是否为 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);//检测 x 的 7,15,23,31 位是否为 1
    val+=(val>>16);//将 val 的高 16 位加到低 16 位上
    val+=(val>>8);//再将 val 的高 8 位加到低 8 位上
    return val&0xff;//保留 val 的最低 byte 信息 为最终结果
}
/* 
 * 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
    int t=~x+1;
    //x=0时,t=0; 
    //x>0时,x符号位=0,t的符号位=1;
    //x<0时,x符号位=1,t的符号位=0;
    // x=0时x|t的符号位 =0,else =1
    return (~((x|t)>>31))&1;
}
/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {//return INT_MIN 
    //一种比较好理解的方式是:溢出从最大跌倒最小(这是我自己yy的)
    //记住机器寸的都是补码,补码公式。。。gg
    //补码=0x80000000时最小(why啊why啊啊啊啊啊) 
    return 1<<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 t=!!(x>>31);//符号位 
    //x>0时,需要给最高位留个0空着,所以右移n-1位 
    return ((!t)&(!(x>>(n+~0))))|(t&!((~x)>>(n+~0)));
    //           >=0                 <0
}//= =!此题极有可能WA !...果然WA了。。 
//(-2147483648[0x80000000],1[0x1]) failed...
//...Gives 1[0x1]. Should be 0[0x0]
/* 
 * 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) {//return x/(2^n)
    //x/(1<<n),  x>>n,,,负数有点麻烦,如果移动的位里有1,则结果+1 
    int t=!!(x>>31);//取符号 
    int tmp=(1<<n)+~0;
    int tt=tmp&x;//取后n位 
    return (x>>n)+((!!tt)&t);//取后n位是否有数 
}
/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {//return -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) {//如果x>0 return 1;else 0 
    //本想return !!!(x<<31),蛋疼的是x==0的时候 
    int t=!!(x>>31);//取符号位 
    return (!t)&(!!x);
}
/* 
 * 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) {//return x<=y
    //本想直接return !!!((y-x)>>31),,没考虑溢出 
    //x*y>=0时,不会溢出,
    //else 若x>0.则y<0,return 0;
    //     若x<0.则y>0,return 1;
    int tx=!!(x>>31);
    int ty=!!(y>>31);
    int t=!!((y+(~x+1))>>31);//y-x  
    return ((!t)&(!(tx^ty)))|((tx^ty)&tx);
}
/*
 * 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) {//return floor(log base 2 of x)
    /*int M=1,t=0;
     *while (M<=x)M<<=1,t++;
     *return --t  //no loops,,,fuck
     */
    //二分法,每次取前半段,看是否有1存在。32=1<<5,故5次二分 
    int t,s1,s2,s3,s4,s5;
    t=!!(x>>16);//if 前16位有1 则t=1,else =0     1
    s1=t<<4;    //                16        0  
    x>>=s1;         //          取左半边  , 右半边 
    t=!!(x>>8);     //以此类推。。。。 三句一循环     2
    s2=t<<3;
    x>>=s2;
    t=!!(x>>4);     //loop again                      3  
    s3=t<<2;
    x>>=s3;
    t=!!(x>>2);     //again                           4
    s4=t<<1;
    x>>=s4;
    t=!!(x>>1);     //end                             5
    s5=t<<0; 
    return s1+s2+s3+s4+s5;
}
/* 
 * 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) {//return -uf 
    unsigned ans=uf^0x80000000;//符号位取反 
    unsigned tmp=uf&0x7fffffff;//符号位扔掉 
    if (tmp>0x7f800000)return uf;//not a number
    return ans;//为什么是上面一行那个数我也不知道。。。 
}
/* 
 * 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 s=x&(1<<31);//取符号位
    int i=30;//*初始化 i 为 30*
    int exp=(x>>31)?158:0;//初始化 exp
    int frac=0;//用来保存尾数10
    int delta;//保存精度
    int frac_mask=(1<<23)-1;//frac_mask 低 23 位全 1,高 9 位全 0
    if (x<<1){//如果 x 不为 0 也不为-2^31
        if(x<0)x=-x;//x=|x|
        while(!((x>>i)&1))i--;//x 最高位 1 权重为 i(编号从 0 开始)
        exp=i+127;//偏置指数 e=E+Bias,Bias=127
        x=x<<(31-i);//扔掉 x 前面的 0
        frac=frac_mask&(x>>8);//frac 取尾数(取 x 的高 23 位)
        x=x&0xff;//保留 x 的末 8 位,将处理的精度
        delta=x>128||((x==128)&&(frac&1));//处理精度,四舍五入
        frac+=delta;//加上精度
        if(frac>>23){//如果尾数溢出
            frac&=frac_mask;//取尾数的后 23 位
            exp+=1;//产生进位
        }
    }
    return s|(exp<<23)|frac;//返回最后结果
}
/* 
 * 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) {
    unsigned s=uf&(1<<31); //取符号位 
    int exp=(uf>>23)&0xff; //取阶码 
    int frac=uf&((1<<23)-1); 
    if((exp^0xff)){ //如果阶码部分不为 255 
        if(!exp){ frac<<=1;} //阶码部分不为 0将尾数左移一位即可 
        else{ //如果阶码为 0 
            exp++; //将阶码加 1 
            if(exp==255)frac=0; //所得阶码为 255,将尾数设置为 0,表示无穷大  
        } 
    }//省略 else 情况,即 uf 为 NaN 
    return s|(exp <<23)|frac;
}

推荐阅读