• CSAPP DataLab


    断断续续做了两天可算做的差不多,,

    注意不同版本的题目可能会有所不同,搜了很多他们的题目和现在官网给的实验题都不一样,自己独立思考完整做一遍顺便记录一下。

    PS:刚开始这些难度为1的题有的说实话我都做了挺久的,不过到后面虽然难度上升了,但是确越做越有感觉了,另外完整做一遍感觉很有意思,这些题总体感觉就是让你自己把那些运算符< ,> ? 什么的自己使用位级运算手动实现一遍,知道底层是怎样运作的。

    一,

    bitXor: 

    /* 
     * bitXor - x^y using only ~ and & 
     *   Example: bitXor(4, 5) = 1
     *   Legal ops: ~ &
     *   Max ops: 14
     *   Rating: 1
     */
    int bitXor(int x, int y) {
      return 2;
    }
    View Code

     

    题目如图,

    题目解释:使用~ & 完成 ^ 位运算,虽然难度很低,但是我也推导了半天,,

    思路:异或可以理解为取出a,b之中不相同的位,& 就是取出为都为1的位,那么我们可以先取出同为1的,然后取反,就得到了同为0或者不相同的位,即 ~(a&b) ,接着,我们取出同为0的,取反,得到同为1或者不相同的位,即~(~a&~b), 接着,再取这两个的交集,就是我们所需要的不相同的位。即

    int bitXor
    r(int x, int y) {
      return (~(x&y))&(~(~x & ~y));
    }

    tmin:返回补码整数的最小值,补码表示就是有个符号位,int类型shi是4个字节,32位,所以最小值就是1<<31  ,符号位为1,其他位都为0

    /* 
     * tmin - return minimum two's complement integer 
     *   Legal ops: ! ~ & ^ | + << >>
     *   Max ops: 4
     *   Rating: 1
     */
    int tmin(void) {
    
      return 1<<31;
    
    }

    isTmax:如果是补码最大值就返回1,否则返回0,Tmax是  0x7FFFFFFF,

    虽然还是一个简单题,但是我又想了很久,而且感觉这样子很麻烦。。

    思路:核心是利用溢出。

    理性分析了一下,想要返回0,1,那么肯定要用到 ! 运算符,一个常数的非是0,除了!0=1,所以,我们需要构造出来一个表达式,让x为Tmax时候值刚好为0,其他情况值都为1,这样子取非,就可以得到结果了。我这里想的是如果X是Tmax,那么~x就是Tmin,所以判断~x是不是Tmin,利用溢出来判断,给~x加上-1(~0),Tmin情况下会产生溢出,然后会进行符号截断,Tmin-1 = Tmax,再利用Tmax+Tmin+1 = 0得到我们想要的0,再取非即可。

    int isTmax(int x) {
      return !((~x+~0) + ~x + 1);
    }

    四,

    allOddBits:

     五,

    negate:输入一个x,返回-x,

    思路:第一眼看过去感觉很简单,实际上就是很简单,直接取反加一就行了,取反刚好就是自己的相反数-1,再加上一就可以了,不知道这个题为什么难度是2

    /* 
     * negate - return -x 
     *   Example: negate(1) = -1.
     *   Legal ops: ! ~ & ^ | + << >>
     *   Max ops: 5
     *   Rating: 2
     */
    int negate(int x) {
        return (~x) + 1;
    }

     六,

    isAsciiDigit:判断一个数是不是在 48-57,包括57,48.刚开始没什么思路,不过感觉肯定是要构建出来一个0或者1的在特定情况下,最后参考了一下网上的,说实话让我自己做肯定做不出来,感觉很巧妙

    思路:这个题实际上就是为了判断两个表达式的真假,x-48>=0  和  x-57 <= 0 ,将这两个表达式转换一下, 用到了第五题的结论,-48=~48+1,-57=~57+1,判断>=0或者<=0,看符号位就可以了,符号位为1表示<0,符号位为0表示>=0,得到符号位自然是将这个32位数右移31位,

    综上,我们得到下面结论,如果 (x+~48+1)>>31  为0,那么x>=48,如果 (x+~57+1)>>31  为1 ,那么x<57,然后取前者的非,和后者进行&运算,同时满足条件即说明x>=48,x<57。

    很明显,漏掉了边界57,x=57时,x-57刚好为0,移位之后得到的是0,所以我们将第表达式二改为  (x+~58+1)   x为57时,结果仍为负数,符号位为1,将57这种情况成功纳入到符号位为1的情况, 

    * 
     * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
     *   Example: isAsciiDigit(0x35) = 1.
     *            isAsciiDigit(0x3a) = 0.
     *            isAsciiDigit(0x05) = 0.
     *   Legal ops: ! ~ & ^ | + << >>
     *   Max ops: 15
     *   Rating: 3
     */
    int isAsciiDigit(int x) {
        return !((x + (~48 + 1)) >> 31)&((x + (~58 + 1)) >> 31);
    }

    conditional:即自己使用位级符号实现一个三目运算符

     这个题说实话没有看懂。。

    八,

    isLessOrEqual(x,y)  如果y>=x  返回1,否则返回0

    这个题感觉思想和前面的很像,判断y-x>=0是否成立,即判断y-x的符号位,如果是0的话就表明成立,1表示不成立,因为符号位1表示为负数。这样子就简单了,-x = ~x+1  ,符号位>>31即可得到,所以可以构造出表达式:(y+~x+1)>>31    ,要求是成立了返回1,所以再取个非就可以了。

    /* 
     * isLessOrEqual - if x <= y  then return 1, else return 0 
     *   Example: isLessOrEqual(4,5) = 1.
     *   Legal ops: ! ~ & ^ | + << >>
     *   Max ops: 24
     *   Rating: 3
     */
    //即使用位级运算判断y-x>=0表达式是否成立,看符号位
    int isLessOrEqual(int x, int y) {
      return !((y+(~x+1))>>31);
    }

    九,

    logicalNeg:使用其他的位级运算符实现 ! 运算,

    。。刚开始思路错了,想着直接 x^0^1,忘记考虑了x是32位的,和0异或出来一般不会是1

    思路:两种情况,一种是! 0 = 1, 其他数  ! num = 0,所以其实只要想办法把这两种情况区分开来就可以了。个人感觉区分的话肯定是要找出0的特点的,很明显,0的相反数是它本身,其他数的相反数是他的负数。利用这一点,我们可以让x的相反数(~x+1)的符号位(>>31)和x进行异或,除了0以外结果都是1,由于不能取反,所以用if判断一下就可以了。

    int logicalNeg(int x) {
        if((((~x+1)>>31)^(x>>31)))
            return 0;
      return 1;
    }

    十,

      howManyBits:返回表达x最少需要多少位

    思路:感觉跟十进制转换为2进制差不多。我想的是我们确定位数那么就需要判断x的范围,如果在 2^(i-1)---2^i 之间,那么就需要i位刚好可以表示,不过由于是有符号整数,所以需要再加上一位符号位,就是i+1位,所以我们只需要将logx的值向上取整,再加上1即可,这是对整数而言,对于负数来说,将负数转换为正数进行计算,最后同样加上一即可,至于确定x的范围,循环除2(>>1),直到x为0为止。不过这里有两种特殊情况,那就是Tmin和-1,Tmin由于是一个负数,如果取他的相反数进行计算的话,不存在与之对应Tmax,会导致不可预期的结果,另外-1只需要一位即可表示,+1需要两位,这两种特殊情况我想的是直接if判断一下,返回相应的值,如果有更好的方法欢迎讨论。

    int howManyBits(int x) {
        int i=1;     //符号位
        int y=x;
        if(x==-1)    //特殊情况
            return 1;
        if(x==0x80000000)
            return 32;
        if(x>>31)    //负数取相反数
            y = ~x+1;
    
        while(y){
            y = y>>1;   // 除2
            i++;
        }
      return i;
    }

    。。。剩下的浮点数的题,,,,浮点数那块看了几次都没看完,,等看完了再做吧!

      

     

  • 相关阅读:
    JAVA面向对象概述
    练习
    字符串
    图形代码
    assets转到内外部存储
    file存储
    sp存储
    Intent练习
    存储登录
    存储
  • 原文地址:https://www.cnblogs.com/eenio/p/11521248.html
Copyright © 2020-2023  润新知