Datalab-handout数据表示实验


根据bits.c中的要求补全以下的函数:
 
 
intbitXor(int x, int y);
inttmin(void);
intisTmax(int x);
ntallOddBits(int x);
int negate(int x);
intisAsciiDigit(int x);
int conditional(int x, int y, int z);
intisLessOrEqual(int x, int y);
intlogicalNeg(int x);
inthowManyBits(int x);
unsignedfloat_twice(unsigned uf);
unsigned float_i2f(int x);
int float_f2i(unsigned uf);
 
 

本次为一次计算机系统实验,就是使用一些基本的运算符来实现函数功能。

//1

/* 
 * bitXor - 仅允许使用~和&来实现异或 
 *   例子: bitXor(4, 5) = 1
 *   允许的操作符: ~ &
 *   最多操作符数目: 14
 *   分值: 1
 */


/* 
 * tmin - 返回最小的二进制补码 
 *   允许的操作符: ! ~ & ^ | + << >>
 *   最多操作符数目: 4
 *   分值: 1
 */


//2
/*
 * isTmax - 如果x是最大的二进制补码,返回1;否则,返回0
 *   允许的操作符: ! ~ & ^ | +
 *   最多操作符数目: 10
 *   分值: 2
 */
/* 
 * allOddBits - 如果所有奇数位都为1则返回1;否则返回0
 *   例子: allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
 *   允许的操作符: ! ~ & ^ | + << >>
 *   最多操作符数目: 12
 *   分值: 2
 */


/* 
 * negate - 返回-x 
 *   例子: negate(1) = -1.
 *   允许的操作符: ! ~ & ^ | + << >>
 *   最多操作符数目: 5
 *   分值: 2
 */


//3
/* 
 * isAsciiDigit - 如果x是ascii码中的0~9,返回1;否则返回0
 *   例子: isAsciiDigit(0x35) = 1.
 *            isAsciiDigit(0x3a) = 0.
 *            isAsciiDigit(0x05) = 0.
 *   允许的操作符: ! ~ & ^ | + << >>
 *   最多操作符数目: 15
 *   分值: 3


/* 
 * conditional - 实现x?y:z 
 *   例子: conditional(2,4,5) = 4
 *   允许的操作符: ! ~ & ^ | + << >>
 *   最多操作符数目: 16
 *   分值: 3
 */


/* 
 * isLessOrEqual - 如果x<=y返回1否则返回0 
 *   例子: isLessOrEqual(4,5) = 1.
 *   允许的操作符: ! ~ & ^ | + << >>
 *   最多操作符数目: 24
 *   分值: 3
 */
//4
/* 
 * logicalNeg - 实现!运算符的功能
 *   例子: logicalNeg(3) = 0, logicalNeg(0) = 1
 *   允许的操作符: ~ & ^ | + << >>
 *   最多操作符数目: 12
 *   分值: 4 


/* howManyBits - 返回将X表示为补码所需的最小有效位数。
 *  例子: howManyBits(12) = 5
 *            howManyBits(298) = 10
 *            howManyBits(-5) = 4
 *            howManyBits(0)  = 1
 *            howManyBits(-1) = 1
 *            howManyBits(0x80000000) = 32
 *  允许的操作符: ! ~ & ^ | + << >>
 *  最多操作符数目: 90
 *  分值: 4
 */


//float
/* 
 * float_twice - 以unsinged表示的浮点数二进制的二倍的二进制unsigned型
 *   参数和结果都会被作为unsigned返回,但是会表示为二进制的单精度浮点值。
 *   允许的操作符: 任何整数或者无符号数操作符包括: ||, &&. also if, while
 *   最多操作符数目: 30
 *   分值: 4
 */


/* 
 * float_i2f - 返回int x的unsigned浮点数的二进制形式
 *   参数和结果都会被作为unsigned返回,但是会表示为二进制的单精度浮点值
 *   允许的操作符: 任何整数或者无符号数操作符包括: ||, &&. also if, while
 *   最多操作符数目: 30
 *   分值: 4
 */


/* 
 * float_f2i - 返回unsigned uf的整型数的二进制形式
 *   参数和结果都会被作为unsigned返回,但是会表示为二进制的单精度浮点值
 *   任何超过范围的数都应该返回 0x80000000u.
 *   允许的操作符: 任何整数或者无符号数操作符包括: ||, &&. also if, while
 *   最多操作符数目: 30
 *   分值: 4
 */


思路及过程实现:
//1 bitXor
思路:异或操作即两操作数值相等为0,相异为1。从而根据其真值表可得出结果。
代码:
int bitXor(int x, int y) {
  return ~(~(x&~y)&~(~x&y));
}




//2 tmin
思路:求32位下的最小值即0x8000 0000,转化为二进制可知,只需1左移31位即可。
代码:
int tmin(void) {
  return 1<<31;
}




//3 isTmax
思路:求该数是否为最大值。首先32位下的最大值为0x7FFF FFFF,左移1位后再加2为0,但是需要排除0xFFFF FFFF,即判断首位是否为1。
代码:
int isTmax(int x) {
  return ((!((x<<1)+2))&(!(x>>31)));
}




//4 allOddBits
思路:判断奇数位是否全为1,则需要先把偶数位置1(通过与0x5555 5555进行或运算),再按位取反,观察若值为0则应返回1。
代码:
int allOddBits(int x) {
  unsigned int a=85;
  unsigned int b=a+(a<<8)+(a<<16)+(a<<24);
  return !~(b|x);
}




//5 negate
思路:返回-x,就要得到其相反数的补码表示,按位取反再加1即可。但是对于32位下int最小值的相反数,由于超出其int的范围则无法表示。
代码:
int negate(int x) {
  return ~x+1;
}




//6 isAsciiDigit
思路:判断是否为ASCII表示的0~9,需要确定x的范围是否在0x30到0x39内,即x减去对应范围值后,判断其符号位是否为0或1。
代码:
int isAsciiDigit(int x) {
  return (!((x+~48+1)>>31))&((x+~58+1)>>31);
}






//7 conditional
思路:实现x?y:z。根据选择关系得(a&y)|(b&z),当x为0时,a=0x0,b=0xFFFF FFFF,而当x为非0值时,a=0xFFFF FFFF,b=0x0。则根据其赋值,得出a=!x+~1+1,b=~!x+1。
代码:
int conditional(int x, int y, int z) {
  return ((!x+~1+1)&y)|((~!x+1)&z);
}



//8 isLessOrEqual
思路:判断x是否小于等于y。分如下情况:
1)若其符号位相异,当x符号位为1则x<y。
2)若符号位相同,则判断y-x的符号位(由于符号位相同,则减运算不会造成数据溢出)。
代码:
int isLessOrEqual(int x, int y) {
  int a=x>>31;
  int b=y>>31;
  int c=a+b;
  int d=((y+~x+1)>>31)&1; 
  return (c&(a&1))|((~c)&!d);
}



//9 logicalNeg
思路:实现!运算符的功能。进行!x操作,当x为0则值为1,当x为非0则值为0。取其相反数y=~x+1,其符号位与原数相反,如下情况特殊:
1)当x=0x0,x、y符号位都为0。
2)当x=0x8000 0000时,x、y符号位都为1。
从而~x&~y则当且仅当x=0x0时,其符号位为1。
代码:
int logicalNeg(int x) {
  return ((~x&~(~x+1))>>31)&1;
}



//10 howManyBits
思路:求其表示的最小位数。利用二分法,先对其右移16bit,若为0,则最低数量为16,根据此思想,继续对其右移8bit、4bit、2bit、1bit。
代码:
//11 float_twice思路:求float的2倍数。1)对于0,即返回0。2)对于指数全1,由于溢出,返回自身。3)对于指数为0,尾数左移一位。当其最高位为1需要指数+1。4) 其他,指数+1,这时指数为全1,则尾数=0。代码: 
 
unsigned float_twice(unsigned uf) {
  int exp=0x7f800000&uf;
  int num=0x007FFFFF&uf;
  unsigned flag=0x80000000&uf;
  int n=(exp>>23)-127;
  if(uf==0x0) return 0;
  if(n==128) return uf;
  if(exp==0)
  {
   if(uf&0x00400000) {num=num<<1;exp=0x00800000;}
  else num=num<<1;
  }else{
   exp=exp+0x00800000;
   n=(exp>>23)-127;
   if(n==128) num=0;
  }
  return (exp|num|flag);
}




//13 float_f2i
思路:返回unsigned uf的整型数的二进制形式。对于指数exp的值分情况讨论:
1)当exp=0或exp-127<0时,返回0。
2)当exp-127>=31时候,超出表示范围,于是返回0x80000000u。
3)当exp-127<=23,根据符号位返回值num>>(23-(exp-127))。
代码:
int float_f2i(unsigned uf) {
  int exp=0x7f800000&uf;
  int num=(0x007FFFFF&uf)+0x00800000;
  unsigned flag=0x80000000&uf;
  int n=(exp>>23)-127;
  if(exp==0) return 0;
  else if(n<0&&n>=-126) return 0;
  else if(n>=31) return 0x80000000u;
  else if(n<=23) num=num>>(23-n);
  else num=num<<(exp-23);
  if(flag==0) return num;
  else return -num;
}



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2019 ITdaan.com

赞助商广告