一、实验要求
实现如下几个问题:
对于int的问题,只能使用基本的位运算,对于float的,可是使用额外的控制语句。
二、预备知识
整型的表示方法:
-
无符号数:
-
有符号数:
无符号数和有符号数直接相互转换:
浮点数表示方法:
一般浮点数采用IEEE 754标准表示 V=
。
-
S为符号位,占1bit。
-
E为阶码,在单精度浮点数中占8位,双精度浮点数中占10位。
-
M为尾数,范围时1~2-e或0~1-e。
根据exp的值,float数可被分为3中情况,以单精度浮点数为例:
-
规格化的值。
-
exp处表示的值为e, e需要满足e>0 && e<255。
-
偏移量Bias=2^8-1=127,阶码 E=e-Bias。
-
frac字段表示的值为f,尾数 M=1+f。
非规格化的值。
-
exp处表示的值为e, e需要满足e=0。
-
偏移量Bias=2^8-1=127,阶码 E=1-Bias。
-
frac字段表示的值为f,尾数 M=f。
特殊值。
-
exp处表示的值为e, e需要满足e=255。
-
偏移量Bias=2^8-1=127,阶码 E=e-Bias。
-
frac字段表示的值为f,f=0是,表示为无穷,f !=0 时,表示NaN。
三、实验代码
异或 bitXor
int bitXor(int x, int y) {
int result = (~(~x&y))&(~(x&~y));
return ~result;
}
//A ~A B ~B A&~B B&~A ~(A&~B) ~(B&~A)
//1 0 0 1 0 1 1 0
//1 0 1 0 0 0 1 1
//0 1 0 1 0 0 1 1
//0 1 1 0 1 0 0 1
有符号最小数 tmin
int tmin(void) {
//1左移31位
int result = 1<<31;
return result;
}
判断是不是有符号最大数 tmax
int isTmax(int x) {
// x==max/x==0xffffff时,~x^(x+1)为0x0000000
// !!(~x)去掉x==0xfffffff的情况
int ret = !!(~x)&!(~x^(x+1));
return ret;
}
判断奇数位是否都为1 allOldBits
int allOddBits(int x) {
//移位和加法构造模式数0xAAAAAAAA
//用模式数&来过滤不同的数
int tmp = (170<<8)+170;
int ret = 0;
tmp = (tmp<<8)+170;
tmp = (tmp<<8)+170;
ret = !((tmp&x)^tmp);
return ret;
}
求负数 negate
int negate(int x) {
//取反码,加一
return (~x)+1;
}
判断是不是ascii数字 isAsciiDight
int isAsciiDigit(int x) {
//高26位应当为0
int high = x&(~63);
//第5,6位应当为1
int low = x&48;
//最后4位加6不应当向第5位进位
int low2 = x&15;
int ret = (!high)&(!(low^48))&(!((low2+6)&(~15)));
return ret;
}
条件判断语句conditional
int conditional(int x, int y, int z) {
//将x转为bool值,0,1
int bool_x = !x;
//利用0、1构造掩码111111、0000000
//0->1111111->0000000;1->11111110->1111111
int mask = ~(~bool_x+1);
//异或清除相同数字
int ret = (~mask&y)^(mask&z)^y^z;
return ret;
}
判断是不是小于等于isLessOrEqual
int isLessOrEqual(int x, int y) {
int nege_x = (~x)+1;
int sum = y+nege_x;
int sign_mask = 1<<31;
//x的符号位
int sign_x = sign_mask&x;
//y的符号位
int sign_y = sign_mask&y;
//如果x<0且y>0,结果位true
//如果x和y符号位相同,且y+(-x)<0,结果为true。符号位相同不会有溢出
int ret = (!!sign_x&!sign_y) | (!(sign_x^sign_y)&!(sign_mask&sum));
return ret;
}
逻辑非 logicNeg
int logicalNeg(int x) {
//0的负数仍未0,符号位不变
//其他数的负数符号位会变
int ret = ~(((~x+1)|x)>>31)&1;
return ret;
}
表示X需要最小的bit位 howMangBits
int howManyBits(int x) {
int b16,b8,b4,b2,b1,b0;
int sign=x>>31;
//如果x为正则不变,否则按位取反(这样好找最高位为1的,原来是最高位为0的,这样也将符号位去掉了)
x = (sign&~x)|(~sign&x);
// 不断缩小范围
b16 = !!(x>>16)<<4;//高十六位是否有1
x = x>>b16;//如果有(至少需要16位),则将原数右移16位
b8 = !!(x>>8)<<3;//剩余位高8位是否有1
x = x>>b8;//如果有(至少需要16+8=24位),则右移8位
b4 = !!(x>>4)<<2;//同理
x = x>>b4;
b2 = !!(x>>2)<<1;
x = x>>b2;
b1 = !!(x>>1);
x = x>>b1;
b0 = x;
return b16+b8+b4+b2+b1+b0+1;//+1表示加上符号位
}
单精度浮点数乘2 floatScale2
unsigned floatScale2(unsigned uf) {
int sign = uf&(1<<31);
int exp = (uf>>23)&255;
//非规格化数
//左移1×2,加上符号位
if(exp==0) return uf<<1 | sign;
//Nan值和无穷大
if(exp==255) return uf;
//规格化数
//exp+1
return uf+(1<<23);
}
浮点数转int floatFloat2Int
int floatFloat2Int(unsigned uf) {
int sign = (uf>>31)&1;
//偏执量为127
int exp = ((uf>>23)&255) - 127;
int frac = uf&(~(511<<23));
//溢出过大
if(exp>31) return 0x80000000u;
//exp小于0
if(exp<0) return 0;
//frac加上默认的1
frac += (1<<24);
//小于24,右移
if(exp<=24) frac = frac >> (24-exp);
//大于24,左移
else if(exp<=30) frac = frac << (exp-23);
//如果符号位为1,转负数
if(sign) frac = ~frac+1;
return frac;
}
2幂次的浮点数表示 floatPower2
unsigned floatPower2(int x) {
// int ret =1;
//太大
if(x>128) return 0x7f800000;
//太小
if(x<-126) return 0;
//加上偏移127
return (x+127)<<23;
}
四、实验结果
Correctness Results Perf Results
Points Rating Errors Points Ops Puzzle
1 1 0 2 8 bitXor
1 1 0 2 1 tmin
1 1 0 2 8 isTmax
2 2 0 2 9 allOddBits
2 2 0 2 2 negate
3 3 0 2 13 isAsciiDigit
3 3 0 2 10 conditional
3 3 0 2 16 isLessOrEqual
4 4 0 2 6 logicalNeg
4 4 0 2 36 howManyBits
4 4 0 2 10 floatScale2
4 4 0 2 20 floatFloat2Int
4 4 0 2 5 floatPower2
Score = 62/62 [36/36 Corr + 26/26 Perf] (144 total operators)