您的位置:首页 > 其它

datalab 数据表示实验

2016-04-30 00:11 302 查看
一直都想每天写博客,然后又经常拖,还有这个是作业,用的时间比较久,然后自己又是脑子不灵活的那种,所以写出来的东西可能会有很多错误,欢迎大家指出来交流交流,互相进步。下次实验室bomb,拆炸弹,不知道能不能坚持把它做完,加油~

1、根据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);

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

*编译:./dlc bits.c
*测试:make btest
./btest
四、实验结果

1. bitXor。思路:根据离散数学的真值表即可得出结果:

/*

* bitXor - x^y using only ~ and &

* Example: bitXor(4, 5) = 1

* Legal ops: ~ &

* Maxops: 14

* Rating: 1

*/

intbitXor(int x, int y) {

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

}

2. tmin。思路:最小值为0x8000 0000,由1左移31即可得到:

/* tmin - return minimum two's complementinteger

* Legal ops: ! ~ & ^ | + << >>

* Maxops: 4

* Rating: 1

*/

inttmin(void) {

return 1<<31;

}

3. isTmax。思路:最大值为0x7fff ffff,加一会变为0x10000000,而此数加上本身后会变为0,本身加本身为0的数只有0和0x1000 0000,故而再将0xffffffff排除即可:

/*

* isTmax - returns 1 if x is the maximum,two's complement number,

* and 0 otherwise

* Legal ops: ! ~ & ^ | +

* Maxops: 10

* Rating: 2

*/

intisTmax(int x) {

return (!(x+1+x+1))&(!!(x+1));

}

4. allOddBits。思路:只有所有奇数位为1的数(二进制),与0x5555 5555进行&预算才会得到0,故而需要得到0x5555 5555即可,将0x5分别左移4、8、16、24得到4个数,然后将这四个数和0x5相加即可得到0x5555 5555:

/*

* allOddBits -return 1 if all odd-numbered bits in word set to 1

* Examples allOddBits(0xFFFFFFFD) = 0,allOddBits(0xAAAAAAAA) = 1

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 12

* Rating: 2

*/

int allOddBits(int x) {

unsigned inta=85;

unsigned intb=a+(a<<8)+(a<<16)+(a<<24);

return !~(b|x);

}

5. isAsciiDigit。思路:x需要>=’0’且<=’9’,将x与临界点作差,然后判断符号位的为0还是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);

}

6. conditional。思路:首先使用t=!x,当x为0时返回1,当x不为0时,返回0,根据题意得到( _ &y)|( _ &z),首先空1,当x不为0,即t=0时,需要t转换为0xffffffff(-1),当t=1时,需要将t转换为0x0(0),,将t-1即可,得到空1为“!x+~1+1”,同理空2为“~!x+1”:

/*

* conditional -same as x ? y : z

* Example: conditional(2,4,5) = 4

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 16

* Rating: 3

*/

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

return ((!x+~1+1)&y)|((~!x+1)&z);

}

7. isLessOrEqual。思路:直接用y-x可能会超出int的表示范围,故而:

A、在x与y同号的情况下转换为p=y-x>=0,然后p符号位(p>>31)&1为0则返回1,符号位1则返回0;

B、 异号时,只要x>=0,就要返回0,否则返回1,由(x>>31)&1能达到该效果;

C、 c=a+b可作为x,y同号异号的判断。

/*

* isLessOrEqual -if x <= y then return 1, else return0

* Example: isLessOrEqual(4,5) = 1.

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 24

* Rating: 3

*/

int isLessOrEqual(int x, int y) {

inta=x>>31;

intb=y>>31;

int c=a+b;

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

intq=!((p>>31)&1);

intr=(c&(a&1))|((~c)&q);

return r;

}

8. logicalNeg。思路:令y=~x+1,考虑x与y的符号位:

A. 当x为0时,两者符号位都为0;

B. 当x=0x8000 0000时,两者符号位都为1;

C. 否则,两者符号位为01或10;

D. 根据离散数学的真值表得出(~x)&(~y).

/*

* logicalNeg -implement the ! operator, using all of

* the legal operators except !

* Examples: logicalNeg(3) = 0, logicalNeg(0) =1

* Legal ops: ~ & ^ | + << >>

* Max ops: 12

* Rating: 4

*/

int logicalNeg(int x) {

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

}

9. howManyBits。思路:二分法,举例x=0000 1000 1001 0000 0000 0000 0000 0000说明:

A. 令y=x>>16=0000 1000 1001 0000,shift16=(!!y)>>4使用(!!y)如果y为0,则返回0,说明前16位都为0,shift16=0,否则!!y=1,shift16=16,使x=x>>shift16=10001001 0000;

B. 同理,令y=x>>8=0000 1000,shift8=(!!y)>>3使用(!!y)如果y为0,则返回0,说明前8位都为0,shift8=0,否则!!y=1,shift8=8,使x=x>>shift8=00001000;

C. 令y=x>>4=0000,shift4=(!!y)>>2使用(!!y)如果y为0,则返回0,说明前4位都为0,shift4=0,否则!!y=1,shift4=4,使x=x>>shift4=00001000;

D. 令y=x>>2=0000 10,shift2=(!!y)>>1使用(!!y),如果y为0,则返回0,说明前2位(原始的x[27]x[26])都为0,shift2=0,否则!!y=1,shift2=2,使x=x>>shift2=000010;

E. 令y=x>>1=0000 1,shift1=(!!y)>>1使用(!!y)如果y为0,则返回0,说明前1位都为0,shift1=0,否则!!y=1,shift2=2,使x=x>>shift1=00001;

F. 然后令sum=2+ shift16+shift8+shift4+shift2+shift1即可;

G. 对于负数取反码即可,对于-1和0特殊考虑。

/* howManyBits - return the minimum number of bitsrequired to represent x in

* two's complement

* Examples: howManyBits(12) = 5

* howManyBits(298) = 10

* howManyBits(-5) = 4

* howManyBits(0) = 1

* howManyBits(-1) = 1

* howManyBits(0x80000000) = 32

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 90

* Rating: 4

*/

int howManyBits(int x) {

intshift1,shift2,shift4,shift8,shift16;

int sum;

intt=((!x)<<31)>>31;//x为0时,t(二进制)全为1,x不为0时,全为1

intt2=((!~x)<<31)>>31;//当x为-1时,t2全为1,否则,全为0

//printf("x=%x\n",x);

intop=x^((x>>31));//正数不变,负数取反

//printf("op=%x\n!!(op>>16)=%x\n",op,!!(op>>16));

shift16=(!!(op>>16))<<4;//如果高十六位全为0,则0左移4位,不全为0,则1左移4(表示op要右移2^4位)位

op=op>>shift16;

shift8=(!!(op>>8))<<3;

op=op>>shift8;

shift4=(!!(op>>4))<<2;

op=op>>shift4;

shift2=(!!(op>>2))<<1;

op=op>>shift2;

shift1=(!!(op>>1));

op=op>>shift1;

//printf("shift16=%x shift8=%x shift4=%x shift2=%xshift1=%x\n",shift16,shift8,shift4,shift2,shift1);

sum=2+shift16+shift8+shift4+shift2+shift1;

//printf("t=%x sum=%x\n",t,sum);

return(t2&1)|((~t2)&((t&1)|((~t)&sum)));

}

10. float_twice。思路:分三种情况考虑

A. 当exp=0xff时,直接返回本身;

B. 当exp=0时,分两种情况考虑:

a) 当uf[22]=0时,直接即可frac<<1;

b) 当uf[22]=1时,exp++,然后frac<<1;

C.否则,exp++,然后分两种情况:

a) 当exp==0xff,令frac=0即可。

b) 否则不做处理。

/*

* float_twice -Return bit-level equivalent of expression 2*f for

* floating point argument f.

* Both the argument and result are passed asunsigned int's, but

* they are to be interpreted as the bit-levelrepresentation of

* single-precision floating point values.

* When argument is NaN, return argument

* Legal ops: Any integer/unsigned operationsincl. ||, &&. also if, while

* Max ops: 30

* Rating: 4

*/

unsigned float_twice(unsigned uf) {

//scanf("%x",&uf);

unsigned intexp=0x7f800000&uf;

unsigned intfrac=0x007fffff&uf;

unsigned ints=0x80000000&uf;

if(((~exp)&0x7f800000)==0){//exp=11111111

//printf("%x\n",uf&0xff800000);

return uf;

}else{

if(exp==0){

if((0x00400000&uf)==0){

frac=frac<<1;

}else{

exp=0x00800000;

frac=frac<<1;

}

}else{

exp=exp+0x00800000;

if(((~exp)&0x7f800000)==0)

frac=0;

}

//unsigned intx=(exp|frac|s);

//printf("%x\n%x\n%x\n%x\n",s,exp,frac,x);

return(exp|frac|s);

}

}

11. float_i2f。思路:首先我们需要知道int型的范围为-2^31~2^31-1主要有两种情况:

A. 用(二进制)科学计数法表示int型数时,尾数位数<=23,例如0x00008001,此时将0x8001左移24-16=8位得到frac,而exp则127+16-1;

B. 当尾数位数>23时,找到位数最末一位记作x[i],然后对尾数的舍去分3种情况考虑,初始化c=0:

a) 当x[i-1]=1且x[i-2]、x[i-3]…x[0]都为0(即要偶端舍入情况),且x[i]=1,令c=1(此处frac若是全为1,则会导致frac+c超出范围,这是bug,当还是通过了);

b) 当x[i-1]=1且x[i-2]、x[i-3]…x[0]不都为0,令c=1(与a存在同样的bug);

c) 除a、b的情况,c=0;

C. 其他特殊情况再考虑一下就好了;

/*

* 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-levelrepresentation of a

* single-precision floating point values.

* Legal ops: Any integer/unsigned operationsincl. ||, &&. also if, while

* Max ops: 30

* Rating: 4

*/

unsigned float_i2f(int x) {

unsigned abs=x;

unsigneds=0x80000000&x;

unsignedtem=0x40000000;

unsignedexp_sign=0;

unsigned exp=0;

unsigned frac;

unsigned c=0;

if(x==0)

return x;

elseif(x==0x80000000)

return(s+(158<<23));

else{

if(x<0)

abs=-x;

while(1){

if(tem&abs)

break;

tem=tem>>1;

//printf("%x\n%x\n",tem,abs);

exp_sign=exp_sign+1;

}

// printf("exp_sign=%d\nx=%x\n",exp_sign,x);

frac=(tem-1)&abs;

//printf("frac=%x\n",frac);

if(31-1-exp_sign>23){//wei shu da yu 23wei de qingkuang

inti=30-exp_sign-23;

if((frac<<(31-(i-1)))==0x80000000){//ouduan quzhi

if((frac&(1<<i))!=0)

c=1;

}

elseif((frac&(1<<(i-1)))!=0)//dayu yiban jia 1

c=1;

frac=frac>>i;

}

else

frac=frac<<(23-(31-exp_sign-1));

exp=157-exp_sign;

//printf("exp=%d\n s=%x\n",exp,s);

//printf("frac=%x\n",frac);

//printf("result=%x\n",(s+(exp<<23)+frac+c));

return (s+(exp<<23)+frac+c);

}

}

12. float_f2i。思路:exp为0,x=(-1)^s*0.frac*2^(-126);否则x=(-1)^s*1.frac*2^(exp-127)分情况考虑:

A. 根据float转为int是向0舍入的情况,当exp=0或者exp<127(由exp-127<0得到);

B. 令exp_sign=((exp>>23)-127)>=0,根据x=(-1)^s*1.frac*(exp-127),

a) exp_sign=0,x=1.x[22]x[21]…x[0]-->x=1;

b) exp_sign=1,x=1x[22].x[21]…x[0]-->x=1x[22];

c) exp_sign=2,x=1x[22]x[21].x[20]…x[0]-->x=1x[22]x[21];

d) exp_sign=23,x=1x[22]x[21]x[20]…x[0]-->x=1x[22]x[21]…x[0]

e) exp_sign=30,x=1x[22]x[21]x[20]…x[0]-->x=1x[22]x[21]…x[0]0…0(共31位)

f) exp_sign=32,x=1x[22]x[21]x[20]…x[0]-->x=1x[22]x[21]…x[0]0…0(共32位),此时,因为int为有符号,只有0x0000 00000能被表示出来,其他都是NAN;

C. 当exp_sign=((exp>>23)-127)>=33,NAN

/*

* float_f2i -Return bit-level equivalent of expression (int) f

* for floating point argument f.

* Argument is passed as unsigned int, but

* it is to be interpreted as the bit-levelrepresentation of a

* single-precision floating point value.

* Anything out of range (including NaN andinfinity) should return

* 0x80000000u.

* Legal ops: Any integer/unsigned operationsincl. ||, &&. also if, while

* Max ops: 30

* Rating: 4

*/

int float_f2i(unsigned uf) {

intexp=0x7f800000&uf;

unsigneds=0x80000000&uf;

intfrac=0x007fffff&uf;

intfrac2=frac+0x008fffff;

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

//printf("uf=%x\n",uf);

if(exp==0x7f800000)

return0x80000000u;

else if(exp==0)

return 0;

elseif(exp_sign<=-1&&exp_sign>=-126)

return 0;

elseif(exp==31&&frac==0&&s!=0)

return0x80000000;

else if(exp_sign>=31)

return0x80000000u;

elseif(exp_sign<=23)

frac2=frac2>>(23-exp);

else

frac2=frac2<<(exp-23);

if(s==0)

return frac2;

else

return -frac2;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: