一、实验目的:
-
更好地熟悉和掌握计算机中整数和浮点数的二进制编码表示。
-
实验中使用有限类型和数量的运算操作实现一组给定功能的函数,在此过程中加深对数据二进制编码表示的了解。
-
熟悉linux基本操作命令,其中常用工具和程序开发环境。
-
完善bits.c的各个函数,实现其功能,并通过.btest的测试。
二、实验要求
- 尽快熟悉linux基本操作命令,还有其中常用工具和程序开发环境
- 除浮点数函数实现外,只能使用顺序程序结构,禁用if, do, while, for, switch等。
三、实验步骤:
-
修改bits.c
-
语法检查
$ ./dlc bits.c # 简单语法检查 $ ./dlc -e bits.c # 检查操作运算符是否符合需求
dlc 使用的是开源编译器,能通过 gcc 编译不一定能通过 dlc 检查。
-
编译生成可执行文件
$ make # 修改 bits.c 后必须 make,make 完成编译,链接,执行文件生成
-
正确性检查
$ ./btest # 检查 bits 所有函数功能,失败给出测试用例 $ ./btest -f 函数名 # 检查单个函数,失败给出测试用例
四、实验内容(所修改函数代码,功能以及重要代码的解释):
主要操作内容:位操作函数; 补码运算函数; 浮点数表示函数
-
功能:将int型的x最后一位置零
/* * lsbZero - set 0 to the least significant bit of x * Example: lsbZero(0x87654321) = 0x87654320 * Legal ops: ! ~ & ^ | + << >> * Max ops: 5 * Rating: 1 */ int lsbZero(int x) { x = x >> 1;//先向右移一位将最低位舍弃 x = x << 1;//再向左移动,最低位补零 return x; }
-
功能:将int型x的第n个字节翻转
/* * byteNot - bit-inversion to byte n from word x * Bytes numbered from 0 (LSB) to 3 (MSB) * Examples: getByteNot(0x12345678,1) = 0x1234A978 * Legal ops: ! ~ & ^ | + << >> * Max ops: 6 * Rating: 2 */ int byteNot(int x, int n) { int y = 0xff; n = n << 3;//n乘8 y = y << n;//y左移n return x^y;//x异或y即翻转第n个byte }
-
功能:比较int型的x和y的第n个字节,若相同返回0,若不同返回1
/* * byteXor - compare the nth byte of x and y, if it is same, return 0, if not, return 1 * example: byteXor(0x12345678, 0x87654321, 1) = 1 * byteXor(0x12345678, 0x87344321, 2) = 0 * Legal ops: ! ~ & ^ | + << >> * Max ops: 20 * Rating: 2 */ int byteXor(int x, int y, int n) { x=((x>>(n<<3))&0xff);//x提取第n个byte y=((y>>(n<<3))&0xff);//y提取第n个byte return !!(x^y);//x异或y,前面的!!是获得结果的布尔值,若(x^y)==0则结果为0,若(x^y)!=0则结果为1 }
-
功能:实现逻辑与&&
/* * logicalAnd - x && y * Legal ops: ! ~ & ^ | + << >> * Max ops: 20 * Rating: 3 */ int logicalAnd(int x, int y) { x=!!x;//把x化成逻辑值,若x!=0则为1,若x==0则为0 y=!!y;//同理把y化成逻辑值,若y!=0则为1,若y==0则为0 return x&y;//返回x和y相与的值,若x和y均为1则返回1,否则返回0 }
-
功能:实现逻辑或||
/* * logicalOr - x || y * Legal ops: ! ~ & ^ | + << >> * Max ops: 20 * Rating: 3 */ int logicalOr(int x, int y) { x=!!x;//把x化成逻辑值,若x!=0则为1,若x==0则为0 y=!!y;//同理把y化成逻辑值,若y!=0则为1,若y==0则为0 return x&y;//返回x和y相或的值,若x和y均为0则返回0,否则返回1 }
-
功能:实现循环左移n位
/* * rotateLeft - Rotate x to the left by n * Can assume that 0 <= n <= 31 * Examples: rotateLeft(0x87654321,4) = 0x76543218 * Legal ops: ~ & ^ | + << >> ! * Max ops: 25 * Rating: 3 */ int rotateLeft(int x, int n) { int y=~((~0)<<n);//设置y的高32-n位为0,低n位为1 int z=(x>>(32+(~n+1)))&y;//设置z存放x的高n位数,x右移32-n位再和y相与 x=x<<n;//x左移n位 return x+z;//返回x的循环左移值 }
-
功能:如果int型的x中有偶数个1返回0,如果有奇数个1返回1
/* * parityCheck - returns 1 if x contains an odd number of 1's * Examples: parityCheck(5) = 0, parityCheck(7) = 1 * Legal ops: ! ~ & ^ | + << >> * Max ops: 20 * Rating: 4 */ int parityCheck(int x) { x=(x>>16)^x;//把高16位右移16位再和低16位进行按位异或运算,消去偶数个1 x=(x>>8)^x;//和上面原理相同,每次移位将x的低半位数与高半位数进行异或,消去偶数个1 x=(x>>4)^x; x=(x>>2)^x; x=(x>>1)^x; return x&0x1;//最后一位为最终结果,需将前31位置0 }
-
功能:判断int型的x乘2是否溢出,没有溢出返回1,溢出返回0
/* * mul2OK - Determine if can compute 2*x without overflow * Examples: mul2OK(0x30000000) = 1 * mul2OK(0x40000000) = 0 * * Legal ops: ~ & ^ | + << >> * Max ops: 20 * Rating: 2 */ int mul2OK(int x) { int y=((x>>31)&0x1);//取x的第32位即符号位 int z=((x>>30)&0x1);//取x的第31位即最高位 y=y^z;//将符号位和最高位进行异或操作,若两者相同则没有溢出,若不同则溢出 return y^0x1;//和1异或输出题目要求判断结果 }
-
功能:将int型的x乘3/2然后向0舍入
/* * mult3div2 - multiplies by 3/2 rounding toward 0, * Should exactly duplicate effect of C expression (x*3/2), * including overflow behavior. * Examples: mult3div2(11) = 16 * mult3div2(-9) = -13 * mult3div2(1073741824) = -536870912(overflow) * Legal ops: ! ~ & ^ | + << >> * Max ops: 12 * Rating: 2 */ int mult3div2(int x) { x=(x<<1)+x;//x乘3 x+=(x>>31)&0x1;//取符号位和1相与,若x>0则不用加偏移量,若x<0则加偏移量(2^k-1)=1 x=x>>1;//x除以2向0舍入 return x; }
-
功能:判断int型的x-y是否溢出,没有溢出返回1,溢出返回0
/* * subOK - Determine if can compute x-y without overflow * Example: subOK(0x80000000,0x80000000) = 1, * subOK(0x80000000,0x70000000) = 0, * Legal ops: ! ~ & ^ | + << >> * Max ops: 20 * Rating: 3 */ int subOK(int x, int y) { int z=x+(~y+1);//z=x-y int t=(0x1<<31);//设置t的第32位为1,其余位均为0 z=t&z;//提取z的符号位 x=t&x;//提取x的符号位 y=t&y;//提取y的符号位 return !((x^y)&(x^z));//若x和y符号位不同即x和-y符号位相同且x和z的符号位不同则溢出 }
-
功能:实现int型的x的绝对值
/* * absVal - absolute value of x * Example: absVal(-1) = 1. * You may assume -TMax <= x <= TMax * Legal ops: ! ~ & ^ | + << >> * Max ops: 10 * Rating: 4 */ int absVal(int x) { int y=x>>31;//取x的符号位 x=(y&(~x+1))+((~y)&x);//如果x为负数则取反加一,如果x为正数则为其本身 return x; }
-
功能:将unsigned型数据解释为float型数据,若为NaN返回其本身,否则返回其绝对值
/* * float_abs - 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 */ unsigned float_abs(unsigned uf) {//NaN为阶码全1尾数非0 int x=uf&0x7fffffff;//取uf的后31位,并使x的符号位为0 if (x > 0x7f800000) {//如果尾数不为0 return uf;//返回NaN } else {//如果尾数全0 return x;//返回uf的绝对值 } }
-
功能:将浮点数float的位序列转换为int型的位序列,强制类型转换,若为NaN或无穷返回0x80000000u
/* * float_f2i - 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 float_f2i(unsigned uf) { unsigned exp=((uf>>23)&0xff);//取uf的阶码 unsigned frac=(uf&0x7fffff)^0x800000;//取uf的尾数部分,规格化数最高位为1 if (exp>158) {//若阶码大于(127+31)=158时,为正负无穷或NaN return 0x80000000; } else if (exp<127) {//若阶码小于(127+0)=0时,返回0 return 0; } else if (exp>150) {//若阶码大于(127+23)=150时,尾数左移 frac=frac<<(exp-150); } else {//若阶码小于(127+23)=150时,尾数右移 frac=frac>>(150-exp); } if((uf>>31)&0x1){//取uf的符号位 return ~frac+1;//若为负数,返回补码 } else { return frac;//若为正数,返回原码 } }
五、实验结果(在虚拟机中,进行语法检查,编译,正确性检查的截图):
整个bits.c文件进行初步语法检查:
整个bits.c文件进行操作数检查:
整个bits.c文件进行正确性检查: