这个实验是 “离线OJ”,真的难啊搞的死去活来的,最后还是参考(ctrl + c)了往年师兄的方法,才落得个勉强写完。。。本着前人coding后人copying 的想法,姑且发一下自己的代码,与原理的解释
实验是这样的,就是按照一定的限制条件,补全一些函数
1. 按位异或
/*
* bitXor - 仅允许使用~和&来实现异或
* 例子: bitXor(4, 5) = 1
* 允许的操作符: ~ &
* 最多操作符数目: 14
* 分值: 1
*/
由异或的真值表,可以知道 a^b = (a & ~b) | (~a & b)
由或运算的韦恩图,可知道 a | b = (a & ~b)
在逻辑上使用 非,与,实际上操作是按位非(取反),按位(与)
int bitXor(int x, int y) {
return ~(~(x&~y)&~(y&~x));
}
2. 返回最小二进制补码
/*
* tmin - 返回最小的二进制补码
* 允许的操作符: ! ~ & ^ | + << >>
* 最多操作符数目: 4
* 分值: 1
*/
最小即-2147483647,根据补码定义,二进制表示最高位为1,其他全0
int tmin(void) {
return 1<<31;
}
3. x是最大的二进制补码吗?
/*
* isTmax - 如果x是最大的二进制补码,返回1;否则,返回0
* 允许的操作符: ! ~ & ^ | +
* 最多操作符数目: 10
* 分值: 2
*/
最大即2147483647,根据补码定义,二进制表示最高位为0,其他全1
而判断a与b是否相等,可以用异或,如果a^b=0 说明a=b
int isTmax(int x) {
int bm = ~(1<<31);
return !(x^bm);
}
4. 如果所有奇数位都为1则返回1否则返回0
/*
* allOddBits - 如果所有奇数位都为1则返回1;否则返回0
* 例子: allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
* 允许的操作符: ! ~ & ^ | + << >>
* 最多操作符数目: 12
* 分值: 2
*/
判断一个数字奇数位是不是全1,首先把他的偶数位全部置0,再和奇数位全为0的数字比较是否相等,对于一个字节奇数位全部为1的数字:
通过将170左移不同的位数(24,16,8,0)可以得到32位的奇数位为1的数字j
通过与这个数字 j 做 & 运算,可以将偶数位置0,然后再和j比较是否相等
int allOddBits(int x) {
x = x & ((170<<24) + (170<<16) + (170<<8) + 170);
return !(x ^ ((170<<24) + (170<<16) + (170<<8) + 170));
}
5. 取负数
/*
* negate - 返回-x
* 例子: negate(1) = -1.
* 允许的操作符: ! ~ & ^ | + << >>
* 最多操作符数目: 5
* 分值: 2
*/
由补码的定义,负数的补码是其绝对值的补码全部取反后+1,正数和负数的互相转化,通过全部取反后+1都能够实现
int negate(int x) {
return (~x)+1;
}
6. 是ASCII码吗?
/*
* isAsciiDigit - 如果x是ascii码中的0~9,返回1;否则返回0
* 例子: isAsciiDigit(0x35) = 1.
* isAsciiDigit(0x3a) = 0.
* isAsciiDigit(0x05) = 0.
* 允许的操作符: ! ~ & ^ | + << >>
* 最多操作符数目: 15
* 分值: 3
* /
即判断数值是否在 48 ~ 57 之间,可以通过 x-48>=0 和 57-x>=0来判断
判断一个数是否大于等于0,通过观察其符号位可以得到答案,如果符号位为0,那么它大于等于0,反之符号位为1则小于0
当 x-48 的符号位和 57-x的符号位都为0时,满足,返回1
int isAsciiDigit(int x) {
int neg48 = (~48)+1;
int negx = (~x)+1;
int lower = x + neg48;
int upper = 57 + negx;
return !(lower>>31) & !(upper>>31);
}
7. 条件语句的实现