zoukankan      html  css  js  c++  java
  • 实验一

    /* 
     * bitAnd - x&y using only ~ and | 
     *   Example: bitAnd(6, 5) = 4
     *   Legal ops: ~ |
     *   Max ops: 8
     *   Rating: 1
     */
    int bitAnd(int x, int y) {
      
      //~(a&b) = ~a | ~b;
      //a&b = ~(~a | ~b);
      return ~((~x) | (~y));
    }

    根据德摩根律~(x&y) = (~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) {
      int mask = ~(((1<<31)>>n)<<1);
      return mask & x>>n;
    }

    只进行x>>n,如例子,会得到0xf8765432, 所以要用0x0fffffff, 这个值不容易直接得到,但是可以通过0x1000000取反得到。

    /*
     * 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) {
        int mask1 = 0x55555555;
        int mask2 = 0x33333333;
        int mask3 = 0x0f0f0f0f;
        int mask4 = 0x00ff00ff;
        int mask5 = 0x0000ffff;
        x = (x&mask1)+((x>>1)&mask1);
        x = (x&mask2)+((x>>2)&mask2);
        x = (x&mask3)+((x>>4)&mask3); 
        x = (x&mask4)+((x>>8)&mask4); 
        x = (x&mask5)+((x>>16)&mask5);  
      return x;
    }

    算法来自于http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel

    依照http://stackoverflow.com/questions/3815165/how-to-implement-bitcount-using-only-bitwise-operators中的解释是使用了分而治之的方法

    /* 
     * 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|(~x+1)) >> 31) & 1;
    } 

    在补码表示中,只有0可以做到原码和补码的符号位一样,其它任何数的补码和原码的符号位都是相反的。

    应当注意!和~的区别。

    /* 
     * 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 r, c;
        c = 33 + ~n;
        r = !(((x << c)>>c)^x);
        return r;
    }

    判断x的范围是否在-2^(n-1)  ~2^(n-1)-1之间,如果在,则x不会因为左右移动(32-n)发生溢出而改变。

    /* 
     * 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) {  
        //all zeros or all ones  
        int signx=x>>31;  
        //int mask=(1<<n)+(-1);  
        int mask=(1<<n)+(~0);  
        int bias=signx&mask;  
        return (x+bias)>>n; 
    }

    可以见中文CSAPP里的P65有推导过程。我们需要除法向零舍入,但是在负数情况下右移操作会让除法向负无穷舍入,所以需要加上一个bias。

    /* 
     * isPositive - return 1 if x > 0, return 0 otherwise 
     *   Example: isPositive(-1) = 0.
     *   Legal ops: ! ~ & ^ | + << >>
     *   Max ops: 8
     *   Rating: 3
     */
    int isPositive(int x) {
      return !((x>>31)&1);
    }

    根据符号位不同,>>31后可以得到32个1或者32个0。

    /* 
     * 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) {  
      int signx=x>>31;  
      int signy=y>>31;  
      int signSame=((x+(~y))>>31)&(!(signx^signy));  
      int signDiffer=signx&(!signy);  
      return signDiffer|signSame;  
    }  

    当符号相同时, x+(~y) = x-y-1, 如果x-y>0, 那么 x-y-1 >= 0,即符号位为0;  如果x-y<=0, 那么x-y-1<0, 即符号位为1;

    当符号不相同时,若x>0且y<0,那么也符合条件

    /*
     * 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) {
      //binary search +16 +8 +4 +2 +1
      int bCnt = (!!(x>>16))<<4;
      bCnt = bCnt +((!!(x>>(bCnt+8)))<<3);
      bCnt = bCnt +((!!(x>>(bCnt+4)))<<2);
      bCnt = bCnt +(!!(x>>(bCnt+2))<<1);
      bCnt = bCnt +(!!(x>>(bCnt+1)));
      return bCnt;
    }

    以第一步为例,x>>16并且两次逻辑非,那么若x>>16大于零则得到1,说明对应log(x) >= 4,于是1<<4

    /* 
     * 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) {  
      unsigned result;  
      unsigned tmp;  
      tmp=uf&(0x7fffffff);  
      result=uf^0x80000000;  
      if(tmp>0x7f800000)  
            result=uf;  
     return result;  
    }   

    0x7fffffff取取除了符号位剩下的位;

    对0x80000000异或可以让符号位取反;

    if语句中判断0x7f800000,代表着浮点数中的exp字段全为1,即NaN的判断(exp字段全为1,frac字段不为0),当uf is NaN时返回uf,否则返回-f。

    /*    return 1 if x contain even 1s, 0 otherwise;
           assume x = 32w */
    int even_ones(unsigned x)
    {
        int temp = x >> 16 ^ x;
        temp = temp >> 8 ^ temp;
        temp = temp >> 4 ^ temp;
        temp = temp >> 2 ^ temp;
        temp = temp >> 1 ^ temp;
        return !(temp & 1);
    }

    每次将伪码对半比较,判断其中1的个数

    以1100 0110为例,第一次对半比较 1100^0110 = 1010,第二次对半比较 10^10 = 00, 第三次对半比较 0^0=0, 也就是说最后一次比较后得到的数的最后一位为0,则最初的数中含偶数个1,否则含奇数个1;为了取得这个数,我们使用 &1单独拿出,并取!符合题目条件。

    /* 
     * 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 i)
    {
        if(i == 0) return 0;
        unsigned x = i>0?i:-i;
        int sign = i>0?0:1;
        int w = sizeof(int)<<3;
        int j;
        for(j=w-1; j>=0; j--){ //ÕÒµ½×î¸ßλ
            if( (x>>j) & 1) break;
        }
        unsigned bias = 127;
        unsigned exp, frac;
        exp = bias + j;
        if(j <= 23) frac = x<<(23-j);
        else {
            frac = x>>(j-23);
            unsigned mask = (1<<(j-23)) - 1;
            if( (x&mask) > (1<<(j-24)) ) frac++; //ÐèÒªÉáÈëµ½´óÖµ
            else if( (x&mask) == 1<<(j-24)  &&  (frac&1)) frac++; //ÉáÈ뵽żÊý
            if(frac == (1<<24)) exp++; //ÉáÈ뵽żÊý³¬¹ý(1<<24) - 1£¬Ö¸ÊýÐèÒªÔÙ¼Ó1
        }
        return sign<<31 | exp<<23 | frac&0x7FFFFF;
    }

    参考中文书P74一个将12345转为12345.0的实例

    /* 
     * 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(float_bits f){
        unsigned sign = f>>31;
        unsigned exp = (f>>23) & 0xFF;
        unsigned frac = f&0x7FFFFF;
        if(exp == 0) return sign<<31 | frac<<1;
        else if(exp < 254) return sign<<31 | (exp+1)<<23 | frac;
        else if(exp == 254) return sign<<31 | 0xFF<<23;
        else return f;
    }

    了解规范化与非规范化的差别

  • 相关阅读:
    快速删除段落间多余的空行
    平时一些mysql小技巧及常识
    mysql中常用的控制流函数
    按年、季度、月分组&&计算日期和时间的函数
    Excel通过身份证获取出生年月,性别,年龄,生肖,星座,省份等信息总结归纳
    统计图表类型选择应用总结&表数据挖掘方法及应用
    EXCEL如何提取文字中包含的数字?
    一篇说尽Excel常见函数用法
    RStudio中,出现中文乱码问题的解决方案
    R-RMySQL包介绍学习
  • 原文地址:https://www.cnblogs.com/autoria/p/5572738.html
Copyright © 2011-2022 走看看