大部分不难写,但是浮点表示那一块真的很烦
实验要求:
根据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;
}