前言
本来想写点什么。
但是想了想。
感觉好像没什么好写的。
函数分析
1. bitXor函数
函数要求
函数名 | bitXor |
参数 | int , int |
功能实现 | x^y |
要求 | 最大操作数:14,只能使用 ~ 和 & 运算符,将结果返回。 直接使用的常数需位于0~0xFF范围内。 |
/*
* bitXor - x^y using only ~ and &
* Example: bitXor(4, 5) = 1
* Legal ops: ~ &
* Max ops: 14
* Rating: 1
*/
实现分析
根据布尔代数恒等式 x^y = (x & ~y) | (~x & y),使用De Morgan定律将之展开,可得到 x^y = ~ (~x & ~y) & ~ (x & y)。
即得到仅使用位运算符 ~ 和 & 实现 x^y 的表达式。
函数实现
int bitXor(int x, int y) {
return ~(~x & ~y) & ~(x & y);
}
2. getByte函数
函数要求
函数名 | getByte |
参数 | int , int |
功能实现 | 从字x中取出第n个字节 |
要求 | 最大操作数:6,只能使用 ! ~ & ^ | + << >> 运算符,将结果返回。 直接使用的常数需位于0~0xFF范围内。 |
/*
* getByte - Extract byte n from word x
* Bytes numbered from 0 (least significant) to 3 (most significant)
* Examples: getByte(0x12345678,1) = 0x56
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 6
* Rating: 2
*/
实现分析
字节长度固定为8位。取出第n个字节即保留 第n位 ~ 第n+7位,可以使用>>操作符将第n位右移至第1位,使得须保留的变为 第0位~第7位,然后使用掩码 0xFF 消除除低8位之外的所有位。
注意因为保留第n个字节,所以右移操作的实际移位数应为 n*8 即 n>>3。
函数实现
int getByte(int x, int n) {
return x >> (n << 3) & 0xFF;
}
3. logicalShift函数
函数要求
函数名 | logicalShift |
参数 | int , int |
功能实现 | 逻辑右移 |
要求 | 最大操作数:20,只能使用 ! ~ & ^ | + << >> 运算符,将结果返回。 直接使用的常数需位于0~0xFF范围内。 |
/*
* logicalShift - shift x to the right by n, using a logical shift
* Can assume that 0 <= n <= 31
* Examples: logicalShift(0x87654321,4) = 0x08765432
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 3
*/
实现分析
在C语言中,整型类型的常数以二进制补码存在,在使用 >> 操作符进行右移操作时,对于int会进行算术右移(即在进行右移时会自动填充二进制补码表示的最高位的值)。
若希望实现逻辑右移(即在右移时自动填充0),可以在算术右移的基础上使用掩码将自动填充的数值置0。
先得到算术位移n位之后的结果 x >> n。
将0x80000000(即1<<31)同样右移n位,使得此掩码的高n+1位均为1,其余位均为0;然后在左移1位,使得掩码此时高n位均为1,其余位均为0;再进行按位取反,得到高n位均为0,其余位均为1的掩码。
将此掩码与 x>>n 做与操作,从而达成将 x>>n 得到的结果的高n位置0而其余位保持不变(即将符号位之上的位清零)的效果。
从而实现将x逻辑右移n位。
函数实现
int logicalShift(int x, int n) {
return (x >> n) & ~(1 << 31 >> n << 1);
}
4. bitCount函数
函数要求
函数名 | bitCount |
参数 | int |
功能实现 | 计算x中1的数目 |
要求 | 最大操作数:40,只能使用 ! ~ & ^ | + << >> 运算符,将结果返回。 直接使用的常数需位于0~0xFF范围内。 |
/*
* bitCount - returns count of number of 1's in word
* Examples: bitCount(5) = 2, bitCount(7) = 3
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 40
* Rating: 4
*/
实现分析
由于最大操作数为40,且不允许使用循环操作,所以依次检测32位显然会超出操作数要求。
于是自然想到使用分而治之的方式。
1. 可以使用二分法。
- x = (x & mask) + ((x >> n) & mask);
- 使用掩码mask将x分为每n位一组,计算每组中1的位数,将计数结果保存在每组的较低n/2位中(n=2、4、8、16),然后将之相加以获得总位数。
2. 也可以将32位分为4组,每次检测8位,然后将检测的结果累加。
- 也即如下代码所示。
- 使用掩码 0x01010101 进行与运算:cnt += tmp & (x >> n); (n=0、1、2、3、4、5、6、7),从而计算每个字节中1的个数。
- cnt = cnt + (cnt >> 16); 将cnt的低16位和高16为相加并将结果存储在cnt中以处理x中可能存在的进位,确保cnt中包含的是整个32位中1的个数。cnt = cnt + (cnt >> 8); 同样用于处理可能得进位。
- 最后返回cnt的低8位,即为x中所有位中的1的个数。
函数实现
int bitCount(int x) {
int tmp = (0x01 | (0x01 << 8) | (0x01 << 16) | (0x1 << 24));
int cnt = (tmp & x) + (tmp & (x >> 1)) + (tmp & (x >> 2)) + (tmp & (x >> 3)) + (tmp & (x >> 4)) + (tmp & (x >> 5)) + (tmp & (x >> 6)) + (tmp & (x >> 7));
cnt = cnt + (cnt >> 16);
cnt = cnt + (cnt >> 8);
return cnt & 0xFF;
}
5. conditional函数
函数要求
函数名 | conditional |
参数 | int , int |
功能实现 | x?y:z |
要求 | 最大操作数:16,只能使用 ! ~ & ^ | + << >> 运算符,将结果返回。 直接使用的常数需位于0~0xFF范围内。 |
/** conditional - same as x ? y : z
* Example: conditional(2,4,5) = 4
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 16
* Rating: 3
*/
实现分析
x?y:z 即当x为真时返回y,当x为假时返回z。
使用 judge=!!x 对x的值进行判断,当x为真(即x非0)时,judge=1,当x为假(即x为0)时,judge=0。
使用judge构造掩码 mask1 = judge << 31 >> 31 和 mask2 = (!judge) << 31 >> 31。则:
1. 当judge为1时。
- mask1 = 0xFFFFFFFF, mask2 = 0,进行与操作和或操作后,返回y;
2. 当judge为0时。
- mask1 = 0, mask2 = 0xFFFFFFFF,进行与操作和或操作后,返回z。
从而实现x?y:z的效果。
函数实现
int conditional(int x, int y, int z) {
int judge = !!x;
return ((judge << 31 >> 31) & y) | (((!judge) << 31 >> 31) & z);
}
6. tmin函数
函数要求
函数名 | tmin |
参数 | - |
功能实现 | 返回最小的补码 |
要求 | 最大操作数:4,只能使用 ! ~ & ^ | + << >> 运算符,将结果返回。 直接使用的常数需位于0~0xFF范围内。 |
/** tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
实现分析
tmin为 0x80000000 即 1 << 31。
函数实现
int tmin(void) {
return 1 << 31;
}
7. fitsBits函数
函数要求
函数名 | fitsBits |
参数 | int , int |
功能实现 | 判断x的补码能否表示成n位 |
要求 | 最大操作数:15,只能使用 ! ~ & ^ | + << >> 运算符,将结果返回。 直接使用的常数需位于0~0xFF范围内。 |
/*
* fitsBits - return 1 if x can be represented as an
* n-bit, two's complement integer.
* 1 <= n <= 32
* Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
实现分析
mov = 32 + (~n + 1) = 33 + ~n 计算位数差值32-n,即32位整型中剩余的位数。
使用 x << mov >> mov 将x先左移mov位再右移mov位,以检查是否丢失高位信息,再与x进行比较,如果x经左移和右移后仍与原始值相同,则说明未丢失高位信息,使用n位可以表示x的补码。
函数实现
int fitsBits(int x, int n) {
int mov = 33 + ~n;
return !((x << mov >> mov) ^ x);
}
8. dividePower2函数
函数要求
函数名 | dividePower2 |
参数 | int , int |
功能实现 | 计算 |
要求 | 最大操作数:15,只能使用 ! ~ & ^ | + << >> 运算符,将结果返回。 直接使用的常数需位于0~0xFF范围内。 |
/*
* dividePower2 - Compute x/(2^n), for 0 <= n <= 30
* Round toward zero
* Examples: dividePower2(15,1) = 7, dividePower2(-33,4) = -2
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
实现分析
计算 ,即将x进行右移n位。但是有符号数除以2的整数次幂的上,x右移n位等于整除 ,并向下舍入,而当x<0时是向错误的方向舍入(更负的溢出),所以此时应使用偏置 (1 << n) + (~1 + 1) 以实现向上取整。
也即:
- 当 时(即符号位 x>>31 为0时),使用向下取整,直接右移;
- 当 时(即符号位 x>>31 为1时),使用偏置进行向上取整。
函数实现
int dividePower2(int x, int n) {
return (x + (((1 << n) + (~1 + 1)) & (x >> 31))) >> n;
}
9. negate函数
函数要求
函数名 | negate |
参数 | int |
功能实现 | -x |
要求 | 不使用负号。最大操作数:5,只能使用 ! ~ & ^ | + << >> 运算符,将结果返回。直接使用的常数需位于0~0xFF范围内。 |
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
实现分析
逻辑上,从二进制到有符号数有如下公式:
假设x为负数,y为其绝对值(y为无符号数),由于非负数不需要变换,有,即:
从而得到:
其中:
由所得结果 可知:负数可以通过对应的无符号数取反后加1实现到二进制补码的转换。
即 -x = ~x + 1
函数实现
int negate(int x) {
return ~x + 1;
}
10. howManyBits函数
函数要求
函数名 | howManyBits |
参数 | int |
功能实现 | 计算表达x所需的最少位数 |
要求 | 最大操作数:90,只能使用 ! ~ & ^ | + << >> 运算符,将结果返回。 直接使用的常数需位于0~0xFF范围内。 |
/* 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
*/
实现分析
由于最大操作数为90,且不允许使用循环操作,所以依次检测32位显然会超出操作数要求。
于是自然想到使用分而治之的方式,使用二分法,分别检测16位、8位、4位、2位、1位中是否有1的存在,从而逐步逼近,最终得到表达x所需最少的位数。
首先得到x的符号 sign = x >> 31。
在本题中可以通过掩码左移和x右移两种方式实现检测。以下代码使用掩码左移的方式。
- cnt 为表达x所需的最少位数;
- tmp 为掩码;
- judge 判断当前检测的n(n=16、8、4、2、1)位中是否有1的存在。若有,则judge为1*n,若无,则judge为0。
- special 判断x是否为0或-1的特殊情况。
因为在进行右移操作时,有符号数为算术右移,自动填补符号位的值,若x为负数则填充1,会对judge的判断造成影响,所以将负数取反 x = sign ^ x(等价于~x)。
tmp初值为 0xFFFF0000。
使用 x & tmp 判断 高16位 中是否有1存在:
此方式将问题缩小范围,从求解32位数所需要的实际最少位数,变成求解16位数所需要的实际最少位数+16或0。以此方式依次向下查找。
1. 若有1存在:
- 则x一定使用低16位,即至少需要16位来表示,所以judge = 16,cnt += 16;
2. 若无1存在:
- 则x最多使用16位来表示,judge = 0,cnt += 0。
根据cnt的值判断下一步应该判断 高16位中的高8位(tmp = 0xFF000000) 还是 低16位中的高8位(tmp = 0x0000FF00)中是否有1存在。
使用 x & tmp 判断 高8位 中是否有1存在:
1. 若有1存在:
- 则x一定使用低8位,即至少需要cnt+8位来表示,所以judge = 8,cnt += 8;
2. 若无1存在:
- 则x最多使用cnt+8位来表示,judge = 0,cnt += 0。
根据cnt的值判断下一步应该判断 高16位中的高8位中的高4位(tmp = 0xF0000000)、高16位中的低8位中的高4位(tmp = 0x00F00000)、低16位中的高8位中的高4位(tmp = 0x0000F000)还是 低8位中低8位的高4位(tmp = 0x000000F0) 中是否有1存在。
使用 x & tmp 判断 高4位 中是否有1存在:
1. 若有1存在:
- 则x一定使用低4位,即至少需要cnt+4位来表示,所以judge = 4,cnt += 4;
2. 若无1存在:
- 则x最多使用cnt+4位来表示,judge = 0,cnt += 0。
n=2和n=1的情况以此类推。最终得到的cnt是 最大权重的bit所在位,所以最后答案应该加2,但是 特殊情况0和-1则应该加1。
分类考虑 cnt + (1 << (!special)) 从而得到最终的结果。
函数实现
int howManyBits(int x) {
int sign = x >> 31;
int cnt = 0;
int tmp;
int judge;
int special = !x | !(x ^ (~1 + 1));
x = sign ^ x;
tmp = (0xFF | (0xFF << 8)) << 16;
judge = !!(x & tmp) << 4;
cnt += judge;
tmp = 0xFF << (cnt + 8);
judge = (!!(x & tmp)) << 3;
cnt += judge;
tmp = 0xF << (cnt + 4);
judge = (!!(x & tmp)) << 2;
cnt += judge;
tmp = 0x3 << (cnt + 2);
judge = (!!(x & tmp)) << 1;
cnt += judge;
tmp = 0x1 << (cnt + 1);
judge = !!(x & tmp);
cnt += judge;
return cnt + (1 << (!special));
}
11. isLessOrEqual函数
函数要求
函数名 | isLessOrEqual |
参数 | int , int |
功能实现 | 判断x<=y是否成立 |
要求 | 最大操作数:24,只能使用 ! ~ & ^ | + << >> 运算符,将结果返回。 直接使用的常数需位于0~0xFF范围内 |
/** isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
实现分析
按情况分类,将情况可分为四种:xy的符号位均为1、xy的符号位均为0、x符号位为0且y的符号位为1、x的符号位为1且y的符号位为0。
sign_x = x >> 31 判断x的符号位,sign_y = y >> 31 判断y的符号位。
通过判断x、y差值的符号位来判断当x和y符号相同时,x、y的大小关系。因为当差值为正或0时,其符号位均为0,而当其为负时,符号位为1,所以 使用 y-x 来代替 x-y 进行差值的符号判断以减少工作量。
差值的符号位判断 diff = !((y + (~x + 1)) >> 31),当差值为正或0时,diff = 1;当差值为负时,diff = 0。
1. xy的符号位均为1
如果x为Tmin(即 0x80000000)时,为32位整型所能表示的最小负数,必然会小于等于y。其他情况下,diff为1时,x<=y。
2. xy的符号位均为0
diff为1时,x<=y。
3. x符号位为0且y的符号位为1
x必然大于y。
4. x的符号位为1且y的符号位为0
x必然小于y。
函数实现
int isLessOrEqual(int x, int y) {
int sign_x = x >> 31;
int sign_y = y >> 31;
int Tmin = 1 << 31;
int diff = !((y + (~x + 1)) >> 31);
return (sign_x & !sign_y) | (!sign_x & !sign_y & diff) | (sign_x & sign_y & (!(x ^ Tmin) | diff));
}
12. intLog2函数
函数要求
函数名 | intLog2 |
参数 | int |
功能实现 | 计算⌊log2(x)⌋(向下取整) |
要求 | 最大操作数:90,只能使用 ! ~ & ^ | + << >> 运算符,将结果返回。 直接使用的常数需位于0~0xFF范围内。 |
/*
* intLog2 - return floor(log base 2 of x), where x > 0
* Example: intLog2(16) = 4
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 90
* Rating: 4
*/
实现分析
和10. howManyBits函数的实现方法相同,是该函数的简化版本。因为intLog2函数 不需要考虑0和负数的情况,可以直接使用x进行判断。又因为是向下取整,所以判断得到的最大权重的bit所在位即为所求。
在本题中也可以使用掩码左移和x右移两种方式进行计算。以下代码中使用x右移的方式。
- cnt 为表达x所需的最少位数;
- tmp 为x右移后结果;
- judge 判断当前检测的n(n=16、8、4、2、1)位中是否有1的存在。所使用判断的掩码依次分别为0xFFFF、0xFF、0xF、0x3、0x1。若有,则judge为1*n,若无,则judge为0。
tmp初值为 x >> 16。
使用 0xFFFF & tmp 判断 高16位 中是否有1存在:
此方式将问题缩小范围,从求解32位数所需要的实际最少位数,变成求解16位数所需要的实际最少位数+16或0。以此方式依次向下查找。
1. 若有1存在:
- 则x一定使用低16位,即至少需要16位来表示,所以judge = 16,cnt += 16;
2. 若无1存在:
- 则x最多使用16位来表示,judge = 0,cnt += 0。
根据judge的值判断下一步应该判断 高16位中的高8位(tmp = x >> 16 >> 8)还是 低16位中的高8位(tmp = x >> 0 >> 8)中是否有1存在。
使用 0xFF & tmp 判断 高8位 中是否有1存在:
1. 若有1存在:
- 则x一定使用低8位,即至少需要cnt+8位来表示,所以judge = 8,cnt += 8;
2. 若无1存在:
- 则x最多使用cnt+8位来表示,judge = 0,cnt += 0。
根据judge的值判断下一步应该判断 高16位中的高8位中的高4位(tmp = x >> 16 >> 8 >> 4)、高16位中的低8位中的高4位(tmp = x >> 16 >> 0 >> 4)、低16位中的高8位中的高4位(tmp = x >> 0 >> 8 >> 4)还是 低8位中低8位的高4位(tmp = x >> 0 >> 0 >> 4)中是否有1存在。
使用 x & tmp 判断 高4位 中是否有1存在:
1. 若有1存在:
- 则x一定使用低4位,即至少需要cnt+4位来表示,所以judge = 4,cnt += 4;
2. 若无1存在:
- 则x最多使用cnt+4位来表示,judge = 0,cnt += 0。
n=2和n=1的情况以此类推。
函数实现
int intLog2(int x) {
int cnt = 0;
int tmp;
int judge;
tmp = (x >> 16);
judge = (!!((0xFF | (0xFF << 8)) & tmp)) << 4;
cnt += judge;
x = x >> judge;
tmp = (x >> 8);
judge = (!!(0xFF & tmp)) << 3;
cnt += judge;
x = x >> judge;
tmp = x >> 4;
judge = (!!(0xF & tmp)) << 2;
cnt += judge;
x = x >> judge;
tmp = x >> 2;
judge = (!!(0x3 & tmp)) << 1;
cnt += judge;
x = x >> judge;
tmp = x >> 1;
judge = 1 << (!!(0x1 & tmp));
cnt += judge;
return cnt + (~1 + 1);
}
13. floatAbsVal函数
函数要求
函数名 | floatAbsVal |
参数 | unsigned |
功能实现 | 计算f的绝对值的位级表示 |
要求 | 最大操作数:10,可以使用任何整型或无符号数的操作, 包括 || && 和if while等。 |
/** floatAbsVal - Return bit-level equivalent of absolute value of 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 representations of
* single-precision floating point values.
* When argument is NaN, return argument..
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 10
* Rating: 2
*/
实现分析
首先通过左移和右移,抓取8位阶码:exp = (uf << 1) >> 24。
!(exp ^ 255) && (uf << 9) 判断是否为特殊值NAN(E = 0xFFFF 且 M != 0),若是则就直接返回。
否则将符号位置0 (uf << 1) >> 1 即可。
函数实现
unsigned floatAbsVal(unsigned uf) {
unsigned exp = (uf << 1) >> 24;
if (!(exp ^ 255) && (uf << 9))
return uf;
return (uf << 1) >> 1;
}
14. floatScale1d2函数
函数要求
函数名 | floatScale1d2 |
参数 | unsigned |
功能实现 | 计算0.5*f的位级表示 |
要求 | 最大操作数:30,可以使用任何整型或无符号数的操作。 包括 || && 和if while等。 |
/** floatScale1d2 - Return bit-level equivalent of expression 0.5*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
*/
实现分析
首先取出符号位sign和阶码exp。先判断是否是特殊值NAN或INF,若是则直接返回uf,若非则进行下一步规范化判断。
规范化的指数至少为2,否则exp=1或0,此时会考虑 舍入。
若E>1,说明是规范化值,直接使用掩码0x807FFFFF屏蔽x的阶码,然后使用移位后的阶码覆盖即可。
反之,说明是不规范的极小值,考虑舍入。
函数实现
unsigned floatScale1d2(unsigned uf) {
unsigned sign = (uf >> 31) << 31;
unsigned exp = (uf << 1) >> 24;
if (!(exp ^ 255))
return uf;
if (exp > 1)
{
exp = exp - 1;
return (uf & 0x807FFFFF) | (exp << 23);
}
if (!((uf & 3) ^ 3))
uf = uf + 2;
return ((uf >> 1) & 0x7FFFFF) | sign;
}
15. floatFloat2Int函数
函数要求
函数名 | floatFloat2Int |
参数 | unsigned |
功能实现 | 计算(int)f的位级表示 |
要求 | 最大操作数:30,可以使用任何整型或无符号数的操作。 包括 || && 和if while等。 |
/** 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
*/
实现分析
单精度浮点数uf转换为整数int。
- sign = uf >> 31:提取浮点数uf的符号位,存储在sign变量中,其中1表示负数,0表示正数。
- exp = (uf << 1) >> 24:提取浮点数uf的指数部分,存储在exp变量中。
- frac = ((uf << 9) >> 9) + (1 << 23):提取浮点数uf的尾数部分,存储在frac变量中,同时,加上隐藏的1(即 1 << 23),以将其还原为规格化的浮点数。
- bias = 150u - exp:指数的偏置。
使用 (!(exp ^ 255)) 检查特殊情况NaN或INF,返回 0x80000000u。
使用 (!exp) 检查特殊情况浮点数的绝对值小于1,返回 0。
使用 (bias + 7) 检查指数的偏置值是否超出整数范围,若偏置值加7小于0,表示超出整数范围,返回 0x80000000u。
然后根据偏置值计算整数部分,若偏置值为负,表示需要将尾数右移以获得整数部分,若偏置值为正数,表示需要将尾数左移以获得整数部分。
最后,根据符号位来确定整数的正负,如果是负数,将整数取反并加1。
函数实现
int floatFloat2Int(unsigned uf) {
unsigned sign = uf >> 31;
unsigned exp = (uf << 1) >> 24;
unsigned frac = ((uf << 9) >> 9) + (1 << 23);
int bias = 150u - exp;
int tmp;
if (!(exp ^ 255))
return 0x80000000u;
if (!exp)
return 0;
if ((bias + 7) >> 31)
return 0x80000000u;
if (bias >> 31)
tmp = frac << ((~bias) + 1);
else if ((32 + (~bias)) >> 31)
tmp = 0;
else
tmp = frac >> bias;
return (!sign) ? tmp : ((~tmp) + 1);
}
实验总结
在实验过程中着实坎坷,因为在先前在C语言进行程序编写时也少有使用位操作进行运算,对其实是多有忽视,骤然需要严格限定使用位操作进行编写的时候思维方式仍转换不过来,磕磕绊绊不慎流畅。
首先是大部分题目都通过使用巧妙的掩码进行或、与操作进行某些位的置零或者某些位的1判断,刚开始写的时候一直想不到这部分,最初的思路是纯靠左移和右移来进行实现,显然不太能行。后来逐渐开始上手之后就得心应手很多。
像是判断等于的部分起先也很为难,掩码和位操作更加熟练之后就想到可以用异或操作加!来进行判断。
又比如说在bitCount和howManyBit两个函数部分仍然是使用for循环的思维希望能够一位位进行判断,二分法分而治之的思想也是走了不少弯路才试出来的,为了理清楚思路还画了不少流程图,但是后来也可以使用掩码左移和x右移两种方式进行解决。
很多题目都不断的尝试了许多方法,有些行得通,有些不行,有些会更简单,有些则更加复杂,好在虽然过程并非一帆风顺,但最终还是可以说是圆满地完成了实验,实在可以说是边试错边学习。实践果真是检验真理的唯一标准,真正自己亲身去实验,去思考使用底层的位运算来实现函数的时候,才真的对于整型、浮点数、二进制、十六进制、位操作这些等等有了更加深刻,更加深入的印象和理解。