CSAPP 数据表示实验

大部分不难写,但是浮点表示那一块真的很烦

实验要求:

根据bits.c中的要求补全以下的函数:

int bitXor(int x, int y);

int tmin(void);

int isTmax(int x);

nt allOddBits(int x);

int negate(int x);

int isAsciiDigit(int x);

int conditional(int x, int y, int z);

int isLessOrEqual(int x, int y);

int logicalNeg(int x);

int howManyBits(int x);

unsigned float_twice(unsigned uf);

unsigned float_i2f(int x);

int float_f2i(unsigned uf);

在Linux下测试以上函数是否正确,指令如下:

*编译:./dlc bits.c

*测试:make btest

./btest

实验结果:

int bitXor(int x, int y) {

  return~(~((~x)&y)&(~(x&(~y))));

}

//应用离散数学的等值演算的知识

-----------------------------------------------------------------------------------------

int tmin(void) {

  return1<<31;//0x80000000

}

-----------------------------------------------------------------------------------------

int isTmax(int x) {

  return(!(x>>31))&((x+1)>>31);//0x7fffffff

}

-----------------------------------------------------------------------------------------

int allOddBits(int x) {

  return !~(x | 0x55555555);//将偶数位置1后取反,若值为0则说明满足条件

}

-----------------------------------------------------------------------------------------

int negate(int x) {

  return ~x + 1;    //相反数的表示法是取反加1

}

-----------------------------------------------------------------------------------------

int isAsciiDigit(int x) {

  return (!((x +(~(0x30) + 1)) >> 31))&((x + (~(0x3A) + 1)) >> 31);//利用(x-0x30)<=0且(x-0x39)>=0

}

-----------------------------------------------------------------------------------------

int conditional(int x, int y, int z) {

  return((((!!(x^0))<<31)>>31)&y) + ((((!(x ^ 0)) << 31) >>31)&z);//利用异或,若x != 0,(((!!(x^0))<<31)>>31)会得0xffffffff,和y“与”后得y,加号的另一侧原理类似

}

-----------------------------------------------------------------------------------------

int isLessOrEqual(int x, int y) {

    int a = !!(x>> 31);

    int b = !!(y>> 31);

    int c = y + (~x +1);

    return((!(a^b))&(!(c >> 31))) + !!((a^b)&a);//符号位相同,c=0则x<=y;符号位不同,按照x的符号位输出

}

-----------------------------------------------------------------------------------------

int logicalNeg(int x) {

  return((~x&~(~x+1))>>31)&1;

}

//x = 0时,x和~x+1的符号位都为0,特殊的非0数,0x80000000和它的取非+1后的值的符号位都为1。而对于其它值,符号位是相异的

-----------------------------------------------------------------------------------------

int howManyBits(int x) {//二分查找法。。

    int p = x >>31;

    int y =((~x)&p) + (x&(~p));//若x为负数,则取其补码

    int c1 = !!(y>> 16);//判断是否大于16位

    int d1 = 8 + (c1<< 4);//大于16位时为24,小于16位时为8

    int c2 = !!(y>> d1);//大于16位的平移24位,小于16位的平移8位,大于24位或8<<16为1;16< <24和<8为0

    int d2 = d1 + (~3)+ (c2 << 3);//多-4,少+4

    int c3 = !!(y>> d2);

    int d3 = d2 + (~1)+ (c3 << 2);

    int c4 = !!(y>> d3);

    int d4 = d3 + (~0)+ (c4 << 1);

    int c5 = !!(y>> d4);

    int d5 = d4 + c5 +!!y;

    return d5;

}

 -----------------------------------------------------------------------------------------

unsigned float_twice(unsigned uf) {

      if(uf == 0)

            return 0;

      unsigned sym = uf& 0x80000000;//符号位

      int exp = uf& 0x7f800000;//阶码

      int man = uf& 0x007fffff;//尾数

      if(((exp>>23)-127)==128)

            return uf;                          //如果溢出,则返回原值

      if(exp == 0){

            if(uf &0x00400000){        //尾数最高位为1时,指数部分需要+1

                  man =man<<1;

                  exp =exp + 0x00800000;

            }

            else

                  man =man<<1;

      }

      else{

            exp = exp +0x00800000;      //指数部分+1,若指数位全为1,则尾数变0

            if(!(exp^0x7f800000))

                  man =0;

      }

  return (sym | exp | man);

}

 -----------------------------------------------------------------------------------------

unsigned float_i2f(int x) {

      if(x == 0)

            return 0;

      if(!(x<<1))//如果x是-2^31

            return((1<<31) | 0x4f000000 | 0);

      unsigned sym = x& 0x80000000;//符号位

      int num = 30;

      if(x<0)

            x = -x;//取绝对值

      while(!((x>> num)& 1))//不断右移,直到找到1

         num--;

      int exp = num +127;//第一个1以后的数的个数为阶码

      x = x <<(31 - num);

      int man =0x007fffff & (x>>8);//尾数

      x = x & 0xff;//保留x的末八位

      int acc = (x >128) || ((x == 128) && (man & 1));//处理精度

      man += acc;//加上精度

      if(man >>23){//若尾数溢出,取后23位,指数+1

            man &=0x007fffff;

            exp += 1;

      }

  return (sym |(exp<<23) | man);

}

----------------------------------------------------------------------------------------- 

int float_f2i(unsigned uf) {

      unsigned sym = uf& 0x80000000;//符号位

      int exp = uf& 0x7f800000;//阶码

      int num =0x00800000 + (uf & 0x007fffff);//尾数 + 个位数

      int mul =(exp>>23) - 127;

      if (!exp || mul< 0)//当exp=0或exp<127时,返回0

            return 0;

      if(mul >= 31)

            return 0x80000000u;//超出最大表示范围时,则返回最大值

      if (mul >= 23)         //确定小数点的位置

            num = num<< (exp - 23);

      else

            num = num>> (23 - mul);

      if(sym)

            return-num;

      else

            return num;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值