根据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;
}