一、 实验目标:
了解各种数据类型在计算机中的表示方法
掌握C语言数据类型的位级表示及操作
二、实验环境:
计算机(Intel CPU)
Linux操作系统
三、实验内容与步骤
实验前准备:
实验前首先需要安装GCC编译环境,在我的Ubuntu上已经安装了编译环境,展示如下:
根据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
四、实验结果
1. 根据bits.c中的要求补全以下的函数
(1)int bitXor(int x, int y);
①题目描述:
仅允许使用~和&来实现异或
例子: bitXor(4, 5) = 1
允许的操作符: ~ &
最多操作符数目: 14
②大致思路:
依离散数学知识,可以列出对于单个bit的真值表如下:
③ 编程实现:
/* * 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 & ~y)); }
(2)int tmin(void);
①题目描述:
返回最小的二进制补码
允许的操作符: ! ~ & ^ | + << >>
最多操作符数目: 4
②大致思路:
对于32位整数,最小值即为0X 8000 0000,即将1左移31位。
③编程实现:
/* * tmin - return minimum two's complement integer * Legal ops: ! ~ & ^ | + << >> * Max ops: 4 * Rating: 1 */ int tmin(void) { return 1 << 31; }
(3)int isTmax(int x);
① 题目描述:
如果x是最大的二进制补码,返回1;否则,返回0
允许的操作符: ! ~ & ^ | +
最多操作符数目: 10
分值: 2
②大致思路:
可以知道,最大值为0x7fff ffff,加一后将变为0x8000 0000,且此数加上本身后将变为0。本身加本身为0的数只有0和0x8000 0000,因此,只需将0xffffffff排除即可:
③编程实现:
/* * isTmax - returns 1 if x is the maximum, two's complement number, * and 0 otherwise * Legal ops: ! ~ & ^ | + * Max ops: 10 * Rating: 2 */ int isTmax(int x) { return (!(x + 1 + x + 1)) & (!!(x + 1)); }
(4)int allOddBits(int x);
①题目描述:
如果所有奇数位都为1则返回1;否则返回0
例子: allOddBits(0xFFFFFFFD) = 0
allOddBits(0xAAAAAAAA) = 1
允许的操作符: ! ~ & ^ | + << >>
最多操作符数目: 12
②大致思路:
在二进制下,有且仅有所有位为奇数的数与0x5555 5555进行与运算后由0xffff ffff,变为0x0000 0000。因此可以通过对其与0x5555 5555进行与运算并取反再进行取逻辑反获得结果。又因为题干中不允许使用大于256的整数,故需要通过一些操作获得0x5555 5555。
可以通过将0x0505分别进行左移4、8、16、24得到4个数,并将四个数求和获得0x5555 5555。
③编程实现:
/* * allOddBits - return 1 if all odd-numbered bits in word set to 1 * Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1 * Legal ops: ! ~ & ^ | + << >> * Max ops: 12 * Rating: 2 */ int allOddBits(int x) { unsigned int a = 85; unsigned int b = a + (a << 8) + (a << 16) + (a << 24); return !~(b | x); }
(5)int negate(int x);
①题目描述:
返回x的相反数
例子: negate(1) = -1.
允许的操作符: ! ~ & ^ | + << >>
最多操作符数目: 5
②大致思路:
即取反并加一返回即可。
③编程实现:
/* * negate - return -x * Example: negate(1) = -1. * Legal ops: ! ~ & ^ | + << >> * Max ops: 5 * Rating: 2 */ int negate(int x) { return (~x) + 1; }
(6)int isAsciiDigit(int x);
①题目描述:
如果x是ascii码中的0~9,返回1;否则返回0
例子: isAsciiDigit(0x35) = 1.
isAsciiDigit(0x3a) = 0.
isAsciiDigit(0x05) = 0.
允许的操作符: ! ~ & ^ | + << >>
最多操作符数目: 15
②大致思路:
即对于每个输入的x,需要满足x>=‘0’且x<=‘9’,因此可以将x与临界值进行作差。并通过右移31位判断对符号位进行判断是0还是1即可。
③编程实现:
/* * 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) { return (!((x + ~48 + 1) >> 31)) & !!((x + ~58 + 1) >> 31); }
(7)in conditional(int x, int y, int z);
①题目描述:
实现x?y:z
例子: conditional(2,4,5) = 4
允许的操作符: ! ~ & ^ | + << >>
最多操作符数目: 16
②大致思路:
首先,不难想到,对于x的判断可以通过t=!x进行判断实现,当x为0时返回1;当x不为0时返回0。因此,可以将表达式大致转成( _ &y)|( _ &z)的格式进行配凑。
对于前面的空格,当x不为0,即t=0时,需要 t转换为0xffff ffff(-1)。可以通过对1按位取反再加一1获得。
对于后面的空格,当x为0,即t=1时,也需要 t转换为0xffff ffff(-1)。此时直接对t进行取反并加一即可。
③编程实现:
/* * 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) { return ((!x + ~1 + 1) & y) | ((~!x + 1) & z); }
(8)int isLessOrEqual(int x, int y);
①题目描述:
如果x<=y返回1否则返回0
例子: isLessOrEqual(4,5) = 1.
允许的操作符: ! ~ & ^ | + << >>
最多操作符数目: 24
②大致思路:
首先应该很容易会想到直接采用y-x并判断符号位的方法进行判断,但如果作差相减,有可能会发生int类型溢出,因此需要考虑其他方法。
a. 当x,y同号:此时,即可将问题转化为转换为p=y-x>=0,并对p的符号位(通过右移获得)进行判断,获得运行结果。
b.当x,y异号:此时只要x>=0,就可以返回0,否则返回1。
c.是否同号的判断:可以通过对符号位进行求和判断是否同号。
③编程实现:
/* * 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 a = x >> 31; int b = y >> 31; int c = a + b; int p = y + (~x + 1); int q = !((p >> 31) & 1); int r = (c & (a & 1)) | ((~c) & q); return r; }