实验内容
实验要求
实验过程
以下是lab包含的所有文件

在bit.c文件中编写相关代码实现相关函数
使用btest测试函数实现的正确性
bitXor
/*
* bitXor - x^y using only ~ and &
* Example: bitXor(4, 5) = 1
* Legal ops: ~ &
* Max ops: 14
* Rating: 1
*/
int bitXor(int x, int y) {
//异或运算
return ~((~((~(x&y))&x))&(~((~(x&y))&y)));
}
用~ &实现异或操作
异或就是当参与运算的两个二进制数不同时结果才为1,其他情况为0。

可以用与非门实现异或门
tmin
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return 1<<31;
}
返回最小二进制补码整数,int是4B大小,n+1位整数的补码的范围是 – 2n≤ x ≤ 2n–1,因此本题将1左移31位即可
isTmax(x)
/*
* isTmax - returns 1 if x is the maximum, two's complement number,
* and 0 otherwise
* Legal ops: ! ~ & ^ | +
* Max ops: 10
* Rating: 1
*/
int isTmax(int x) {
return (!((~(x+1)) ^ x)) & (!!((x + 1) ^ 0x0));
}
如果是补码的最大值返回1,其余数字返回0
对于int类型,补码的最大值是最高位符号位为0,低31位为1。
allOddBits(x)
/*
* allOddBits - return 1 if all odd-numbered bits in word set to 1
* where bits are numbered from 0 (least significant) to 31 (most significant)
* Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 12
* Rating: 2
*/
int allOddBits(int x) {
int t1 = 0xAA;
int t2 = t1 | (t1 << 8);
int mask = t2 | (t2 << 16);
return !((x & mask) ^ mask);
}
当x的所有奇数位值是1时返回1。
32位数的所有奇数位都是1时是0xAAAAAAAA,以该值为模板通过与操作过滤出所有的奇数位查看是否满足条件。由于本实验规定最多使用8位整数。因此要用0xAA构造出0xAAAAAAAA。
negate
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ~x + 1;
}
补码取反操作规则是按位取反再加1
isAscallDigit
* 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) {
//判断高位是否为0
int high1 = x >> 6;
int t1 = !!high1;
//判断头两位是否为11
int high2 = x >> 4;
int t2 = !(high2 ^ 3);
//判断剩余位是否小于1001
int c = x & 0xF;
int res = c + ~0xA + 1;
int t3 = !!(res >> 31);
return t1 & t2 & t3;
}
当数值x在[0x30,0x39]范围内时返回1否则返回0。
由于只能使用基本运算符,所以从数的特点出发,上下限的二进制数是,0x30 = 110000和0x39 = 111001
根据上下限特点,分为三部分考虑。
1.首先要保证高26位全为0,!!x可以判断x是否为0
2.第五位第六位都为1,使用0x11模板判断即可
3.第四位保证在0000-1001之间,手动模拟补码减法查看符号位即可。
conditional
/*
* 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) {
int mask = ((!!x) << 31) >> 31;
return ((~mask) & z) | (mask & y);
}
实现三目运算符。当x = 0时返回z,否则返回y。
!!x用来判断x是否为0,当x为0时,mask = 0xFFFFFFFF,当x非0时,mask = 0x00000000。
这里要注意:! :代表逻辑取反,即:把非0的数值变为0,0变为1;
~ :表示按位取反,即在数值的二进制表示方式上,将0变为1,将1变为0;
isLessOrEqual
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y) {
//获取符号位
int sign_x = (x >> 31) & 1;
int sign_x = (x >> 31) & 1;
//如果x>0,y<0,返回0
int t1 = !((!sign_x) & sign_y);
//如果x<0,y>0,返回1
int t2 = sign_x & (!sign_y);
//如果x,y正负性相同,模拟补码减法。
int t3 = ((x + (~y) + 1) >> 31) & 1;
//如果两数相等返回1
int t4 = !(x ^ y);
return t4 || (t1 && (t2 || t3));
}
判断x是否小于等于y。由于负数-正数存在溢出问题,因此首先判断符号位。
如果x<0,y>0,返回1
如果x>0,y<0,返回0
如果x,y正负性相同,模拟补码减法。
如果x,y相等,返回1
这里涉及一个多条件模拟。
logicalNeg
/*
* 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) {
int neg = ~x + 1;
int sign = (neg | x) >> 31;
return sign + 1;
}
模拟逻辑取非操作,x=0时返回1,x≠0时返回0。
补码运算中不区分+0,-0,符号位都是0,非0数字取负后符号位为0或1。对于非0数字第二步操作可以得到0xFFFFFFFF,对于0可以得到0x0。最后一步+1可以得到对应的0x0,0x1。
howManyBits
/* howManyBits - return the minimum number of bits required 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) {
//将负数化为整数
//符号位
int sign = x >> 31;
//取正数
x = (sign & (~x)) | ((~sign) & x);
int bit_16, bit_8, bit_4, bit_2, bit_1, bit_0;
//看高16位是否为0以确定低16位是否有效
bit_16 = (!((!!(x >> 16)) ^ 0x1)) << 4;//如果高16位不为0.则低16位有效
x >>= bit_16;
bit_8 = (!((!!(x >> 8)) ^ 0x1)) << 3;
x >>= bit_8;
bit_4 = (!((!!(x >> 4)) ^ 0x1)) << 2;
x >>= bit_4;
bit_2 = (!((!!(x >> 2)) ^ 0x1)) << 1;
x >>= bit_2;
bit_1 = (!((!!(x >> 1)) ^ 0x1));
x >>= bit_1;
bit_0 = x;
int res;
res = bit_0 + bit_1 + bit_2 + bit_4 + bit_8 + bit_16 + 1;//+符号位
return res;
}
本题返回x的二进制补码表示最少需要多少位。第一步将负数化成正数来处理。第二步采用二分思想逐步判断。在(!((!!(x >> 16)) ^ 0x1)) << 4; 中,!!(x >> 16)判断当前高16位是否为0,若为0则返回1,否则返回0。根据结果判断是否进行移位操作做进一步的判断。
floatScale2
//float
/*
* floatScale2 - Return bit-level equivalent of expression 2*f for
* floating point argument f.
* Both the argument and result are passed as unsigned int's, but
* they are to be interpreted as the bit-level representation of
* single-precision floating point values.
* When argument is NaN, return argument
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
unsigned floatScale2(unsigned uf) {
//符号
int S = (uf >> 31) & 0x1;
//阶码
int E = (uf >> 23) & 0xFF;
//尾数
int M = uf & 0x7FFFFF;
//无穷大
if(E == 0xFF)
return uf;
//0
if(E == 0 && M == 0)
return uf;
//非规格数,修改尾数
if(E == 0){
M <<= 1;
return (S << 31) | M;
}
//规格数,修改指数
E++;
return (S << 31) | (E << 23) | M;
}
根据 IEEE 754 浮点数格式返回2*uf。
第一步,分别获取符号,阶码,尾数。
第二步,对于无穷大和0直接返回。
第三步,对于非规格化数将尾数左移1位返回,规格化数将指数加1。
floatFlout2Int
/*
* floatFloat2Int - 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-level representation of a
* single-precision floating point value.
* Anything out of range (including NaN and infinity) should return
* 0x80000000u.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
int floatFloat2Int(unsigned uf) {
//阶码
int S = (uf >> 31) & 0x1;
//阶码
int E = (uf >> 23) & 0xFF;
//尾数
int M = uf & 0x7FFFFF;
//0
if(E == 0 && M == 0)
return 0;
//非规格化数字
if(E == 0)
return 0;
//out of range (including NaN and infinity)
if(E == 0xFF)
return 1 << 31;
//规格化数字
E -= 127;
M = M | (1 << 23);
//考虑表示范围
//超出int表示范围
if(E > 31){
return 1 << 31;
}else if(E < 0){
return 0;
}
//考虑精度问题
//大于23尾数都能保留下来
if(E >= 23){
M <<= (E - 23);
}else{
M >>= (23 - E);
}
if(S)
return ~M + 1;
return M;
根据IEEE 754 float类型转化为int类型。
第一步,分别获取符号位,阶码,尾数。
第二步,当阶码,尾数都为0时表示0,返回0;当阶码为0时表示非规格小数,返回0。
第三步,当阶码为0xFFFFFFFF时表示无穷大,返回0x80000000。
第四步,处理规格数字,32位偏置值是127,先计算阶码E-127,尾数小数点前隐含1,所以在尾数前补1。
第五步,当E > 31 时超过int的最大表示范围,E < 0时低于int的最小表示范围。
第六步,考虑精度问题,当E >=23时左移,E<23时右移。
第七步,处理符号位,符号位为1时返回负数补码。
floatPower2
/*
* floatPower2 - Return bit-level equivalent of the expression 2.0^x
* (2.0 raised to the power x) for any 32-bit integer x.
*
* The unsigned value that is returned should have the identical bit
* representation as the single-precision floating-point number 2.0^x.
* If the result is too small to be represented as a denorm, return
* 0. If too large, return +INF.
*
* Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while
* Max ops: 30
* Rating: 4
*/
unsigned floatPower2(int x) {
int INF = 0xFF << 23;
int exp = x + 127;
if (exp <= 0) return 0;
if (exp >= 255) return INF;
return exp << 23;
}
计算2.0的x次方。
当x过大时,返回INF,IEEE 754的INF表示规则为阶码为0xFF。x+127=阶码,阶码的有效范围是1-254,当阶码为0时返回0,阶码为0xFFFFFFFF时返回INF。
实验结果:

通过阅读
前置知识
实验总结
更加熟悉整数和浮点数的位级表示形式
本文详细介绍了使用位操作符如~&^|+<<>>来实现异或、取反、比较、浮点数尺度调整等函数,涵盖了整数和浮点数的位级表示和计算,包括最小补码整数、最大值检测、位模式检查以及浮点数与整数之间的转换等操作。
1586

被折叠的 条评论
为什么被折叠?



