数据的位运算及补码运算[makefile的简答使用]
要求
(1)位操作
表1-7行出了一组位操作函数。“功能”栏给出函数应实现的输出(即功能),“约束条件”栏指出函数实现必须满足的编码规则,“最多操作符数量”指出设计的函数实现中允许使用的操作符的最大数量。
(2)补码运算
表8-11行出了设计的程序中一组使用整数的补码表示的函数。
表补码运算题目
| 1 |
lsbZero |
将x的最低有效位(LSB)清零 |
仅能使用! ~ & ^ | + << >> |
5 |
| 2 |
byteNot |
将x的第n个字节取反(字节从LSB开始到MSB依次编号为1-4) |
仅能使用! ~ & ^ | + << >> |
6 |
| 3 |
byteXor |
比较x和y的第n个字节(字节从LSB开始到MSB依次编号为1-4),若不同,则返回1;若相同,则返回0 |
仅能使用! ~ & ^ | + << >> |
20 |
| 4 |
logicalAnd |
x&& y |
仅能使用! ~ & ^ | + << >> |
20 |
| 5 |
logicalOr |
x|| y |
仅能使用! ~ & ^ | + << >> |
20 |
| 6 |
rotateLeft |
将x循环左移n位 |
仅能使用! ~ & ^ | + << >> |
25 |
| 7 |
parityCheck |
若x有奇数个1,则返回1;否则,返回0 |
仅能使用! ~ & ^ | + << >> |
20 |
实现
将x的第n个字节取反(字节从LSB开始到MSB依次编号为0-3)
对某一位进行取反,就是和 111…0…11 进行异或操作[倒数第n位为0] ;计算这个数的步骤:将0…01左移n-1位 ;因为不能使用 - 操作符,那么就0…01先左移n位,再右移1位;
1.计算得出111…0…11 [倒数第n位为0]
2.与x进行异或运算 -> 1^0=1,0^0=1; 其他位置与1^后不变
1 2 3 4 5 6
| int byteNot(int x, int n) { int temp = (1 << n) >> 1; printbinary(temp); int result = x ^ temp; return result; }
|
比较x和y的第n个字节(字节从LSB开始到MSB依次编号为0-3),若不同,则返回1;若相同,则返回0
将x,y除第n个字节以外的置0:进行与运算,00…1…0[倒数第n位为1],这样得到的结果就是0…[本来的值]…0,同byteNot函数中的操作
最后再进行一次异或比较 注:要使相同为1,不同为0,需要先对计算后的x,y进行一次取反操作
1.计算得到00…1…0[倒数第n位为1]
2.与x,y进行与运算
3.两个结果进行异或比较
1 2 3 4 5 6
| int byteXor(int x, int y, int n) { int temp_x = (x << n) >> 1; int temp_y = (y << n) >> 1; int result = temp_x ^ temp_y; return result; }
|
注:两次逻辑非的使用 !! 作用是获得逻辑真/假,即1/0;
例:0010 ^ 0000 结果 0010 ,而结果要的是1,就使用!!
总结:其他数据类型向bool值的转换。
后面的代码就不一一分开详述了,思想在注释中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
| #include <iostream> using namespace std;
void printbinary(int x) { for (int i = 16; i >= 0; i--) { if (x & (1 << i)) cout << "1"; else cout << "0"; } cout << endl; }
int lsbZero(int x) { int temp = ~1; int result = x & temp; return result; }
int byteNot(int x, int n) { int temp = (1 << n) >> 1; printbinary(temp); int result = x ^ temp; return result; }
int byteXor(int x, int y, int n) { int temp = (1 << n) >> 1; int temp_x = temp & x; int temp_y = temp & y; int result = !!(temp_x ^ temp_y); return result; }
bool logicalAnd(int x, int y) { int temp = !!x + !!y; bool result = !!(temp & 2); return result; }
bool logicalOr(int x,int y) { int temp = !!x + !!y; bool result = !!(temp); return result; }
int rotateLeft(int x,int n) { int temp = x; int temp2 = temp >> (~n + 17); int temp3 =temp2 & (~1 + (1 << n) + 1); int result = (x << n) | temp3; return result; }
bool parityCheck(int x) { x = x ^ (x >> 1); x = x ^ (x >> 2); x = x ^ (x >> 4); x = x ^ (x >> 8); x = x & 1; return x; }
bool mul2OK(int x) { int x2 = x << 1; int temp_x = x & (1 << 16); int temp_x2 = x2 & (1 << 16); bool result = temp_x ^ temp_x2; return result; }
int mult3div2(int x) { int temp = (x << 1) + x; int flag = temp & (1 << 16); flag = flag >> 16; int result = temp >> 1; result = ((~flag) & result) + (flag & (result + (temp & 1))); return result; }
bool subOK(int x,int y) { int flag_x = x >> 16; int flag_y = y >> 16; int flag = (~y + x + 1) >> 16; bool result = (flag_x ^ flag_y) & (flag_x ^ flag); return !result; }
int absVal(int x) { int temp = ~(1 << 16); int flag = x >> 16; int result = ((~flag) & x) + (flag & ((~x) + 1)); return result; }
int main() { cout<< " ************** 测试案例1 ****************** "<< endl; printf("%d", sizeof(int*));
int x = 5 ; int y = 6 ; int z = 7 ; int m = 0 ; int n = 52222 ; cout << "-----将x的最低有效位(LSB)清零-----" << endl; cout << "输入x值为:"; cin >> x; printbinary(lsbZero(x)); cout << "------将x的第n个字节取反----" << endl; cout << "输入x值为:"; cin >> x; cout << "输入n值为:"; cin >> n; printbinary(byteNot(x,n)); cout << "-----比较x和y的第n个字节,若不同,则返回1;若相同,则返回0-----" << endl; cout << "输入x值为:"; cin >> x; cout << "输入y值为:"; cin >> y; cout << "输入n值为:"; cin >> n; printbinary(byteXor(x,y,n)); cout << "输入x值为:"; cin >> x; cout << "输入y值为:"; cin >> y; cout << "输入n值为:"; cin >> n; printbinary(byteXor(x,y,n)); cout << "-----x && -----" << endl; cout << "输入x值为:"; cin >> x; cout << "输入y值为:"; cin >> y; cout << logicalAnd(x, y) << endl; cout << "-----x || y-----" << endl; cout << "输入x值为:"; cin >> x; cout << "输入y值为:"; cin >> y; cout << logicalOr(x, y) << endl;
cout << "-----将x循环左移n位-----" << endl; cout << "输入x值为:"; cin >> x; cout << "输入n值为:"; cin >> n; cout << "循环前:" << endl; printbinary(x); printbinary(rotateLeft(x, n)); cout << "-----若x有奇数个1,则返回1;否则,返回0-----" << endl; cout << "输入x值为:"; cin >> x; cout << "x的二进制表示为:"; printbinary(x); cout << "结果如下:"; cout << endl << parityCheck(x); cout << endl << "-----计算2*x,如果不溢出,则返回1,否则,返回0-----" << endl; cout << "输入x值为:"; cin >> x; cout << mul2OK(x); cout << endl << "-----计算(x*3)/2,朝零方向取整-----" << endl; cout << "输入x值为:"; cin >> x; cout << mult3div2(x); cout << endl << "----计算x –y,如果不溢出,则返回1,否则,返回0------" << endl; cout << "输入x值为:"; cin >> x; cout << "输入y值为:"; cin >> y; cout << subOK(x,y); cout << endl << "-----求x的绝对值-----" << endl; cout << "输入x值为:"; cin >> x; cout << absVal(x) <<endl ; }
|
在Liunx中用gcc实现
Makefile文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| test: main.o printbinary.o lsbZero.o byteNot.o byteXor.o logicalAnd.o logicalOr.o rotateLeft.o parityCheck.o mul2OK.o mult3div2.o subOK.o absVal.o g++ -o test main.o printbinary.o lsbZero.o byteNot.o byteXor.o logicalAnd.o logicalOr.o rotateLeft.o parityCheck.o mul2OK.o mult3div2.o subOK.o absVal.o
main.o: main.c test.h g++ -c main.c
printbinary.o: printbinary.c test.h g++ -c printbinary.c
lsbZero.o: lsbZero.c test.h g++ -c lsbZero.c
byteNot.o: byteNot.c test.h g++ -c byteNot.c
byteXor.o: byteXor.c test.h g++ -c byteXor.c
logicalAnd.o: logicalAnd.c test.h g++ -c logicalAnd.c
logicalOr.o: logicalOr.c test.h g++ -c logicalOr.c
rotateLeft.o: rotateLeft.c test.h g++ -c rotateLeft.c
parityCheck.o: parityCheck.c test.h g++ -c parityCheck.c
mul2OK.o: mul2OK.c test.h g++ -c mul2OK.c
mult3div2.o: mult3div2.c test.h g++ -c mult3div2.c
subOK.o: subOK.c test.h g++ -c subOK.c
absVal.o: absVal.c test.h g++ -c absVal.c
clean: rm -rf test rm -rf *.o
|
test文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #ifndef _TEST_H #define _TEST_H void printbinary(int x); int lsbZero(int x); int byteNot(int x, int n); int byteXor(int x, int y, int n); bool logicalAnd(int x, int y); bool logicalOr(int x,int y); int rotateLeft(int x,int n); bool parityCheck(int x); bool mul2OK(int x); int mult3div2(int x); bool subOK(int x,int y); int absVal(int x); int main(); #endif
|
main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| #include <iostream> #include "test.h" using namespace std;
int main() { cout<< " ************** 测试案例1 ****************** "<< endl;
int x = 5 ; int y = 6 ; int z = 7 ; int m = 0 ; int n = 52222 ; cout << "-----将x的最低有效位(LSB)清零-----" << endl; cout << "输入x值为:"; cin >> x; printbinary(lsbZero(x)); cout << "------将x的第n个字节取反----" << endl; cout << "输入x值为:"; cin >> x; cout << "输入n值为:"; cin >> n; printbinary(byteNot(x,n)); cout << "-----比较x和y的第n个字节,若不同,则返回1;若相同,则返回0-----" << endl; cout << "输入x值为:"; cin >> x; cout << "输入y值为:"; cin >> y; cout << "输入n值为:"; cin >> n; printbinary(byteXor(x,y,n)); cout << "输入x值为:"; cin >> x; cout << "输入y值为:"; cin >> y; cout << "输入n值为:"; cin >> n; printbinary(byteXor(x,y,n)); cout << "-----x && -----" << endl; cout << "输入x值为:"; cin >> x; cout << "输入y值为:"; cin >> y; cout << logicalAnd(x, y) << endl; cout << "-----x || y-----" << endl; cout << "输入x值为:"; cin >> x; cout << "输入y值为:"; cin >> y; cout << logicalOr(x, y) << endl;
cout << "-----将x循环左移n位-----" << endl; cout << "输入x值为:"; cin >> x; cout << "输入n值为:"; cin >> n; cout << "循环前:" << endl; printbinary(x); printbinary(rotateLeft(x, n)); cout << "-----若x有奇数个1,则返回1;否则,返回0-----" << endl; cout << "输入x值为:"; cin >> x; cout << "x的二进制表示为:"; printbinary(x); cout << "结果如下:"; cout << endl << parityCheck(x); cout << endl << "-----计算2*x,如果不溢出,则返回1,否则,返回0-----" << endl; cout << "输入x值为:"; cin >> x; cout << mul2OK(x); cout << endl << "-----计算(x*3)/2,朝零方向取整-----" << endl; cout << "输入x值为:"; cin >> x; cout << mult3div2(x); cout << endl << "----计算x –y,如果不溢出,则返回1,否则,返回0------" << endl; cout << "输入x值为:"; cin >> x; cout << "输入y值为:"; cin >> y; cout << subOK(x,y); cout << endl << "-----求x的绝对值-----" << endl; cout << "输入x值为:"; cin >> x; cout << absVal(x) <<endl ; }
|
函数示例:
项目结构:
运行结果1:
1将x的最低有效位(LSB)清零
x = 5 即 0101 清零后 0100
2将x的第n个字节取反(字节从LSB开始到MSB依次编号为1-4)
x = 5 n = 2; 取反后 0110
3 比较x和y的第n个字节(字节从LSB开始到MSB依次编号为1-4),若不同,则返回1;若相同,则返回0
x = 5 即0101 ; y = 6 即0110 ; n = 2; 第二个字节不一样,返回0
x = 6 即0110 ; y = 7 即0111 ; n = 2; 第二个字节一样,返回1
4 x&& y
x = 10 ; y =-10 ; 都是非0,返回1
5 x|| y
x = 10 ; y =0 ; 不全0,返回1
6 将x循环左移n位
x = -1002 n = 5;
循环左移前:11111110000010110
循环左移后:11000001011011111
7 若x有奇数个1,则返回1;否则,返回0
x = 103 ;即00000000001100111 5个1返回1
8 计算2*x,如果不溢出,则返回1,否则,返回0
x = 5000; 溢出返回0
9 计算(x*3)/2,朝零方向取整
x = -104 -104*3/2 = -156 返回-156
x = 105 105*3/2 = 157.5 返回 157
10 计算x –y,如果不溢出,则返回1,否则,返回0
x = 50000 y = -50000 溢出返回1
11 求x的绝对值
x = -1900 返回1900
运行结果2:
1将x的最低有效位(LSB)清零
x = 13 即 1101 清零后 1100
2将x的第n个字节取反(字节从LSB开始到MSB依次编号为1-4)
x = 12 即 1100 n = 3; 取反后 1000
3 比较x和y的第n个字节(字节从LSB开始到MSB依次编号为1-4),若不同,则返回1;若相同,则返回0
x = 12 即1100 ; y = 13 即1001 ; n = 2; 第二个字节一样,返回1
x = 12 即1100 ; y = 13 即1001 ; n = 1; 第1个字节不一样,返回0
4 x&& y
x = 10 ; y = 0 ; y为0,返回 0
5 x|| y
x = 0 ; y = 0 ; x,y全0,返回0
6 将x循环左移n位
x = 998 n = 4;
循环左移前:11111110000010110
循环左移后:11000001011011111
7 若x有奇数个1,则返回1;否则,返回0
x = 120 ;即00000000001100111 4个1返回0
8 计算2*x,如果不溢出,则返回0,否则,返回1
x = 20; 不溢出返回0
9 计算(x*3)/2,朝零方向取整
x = -105 -105*3/2 = -157.5 返回-157
10 计算x–y,如果不溢出,则返回1,否则,返回0
x = 500 y = -500 不溢出返回1
11 求x的绝对值
x = 1900 返回1900
注:第8个求两倍溢出的可能有些逻辑问题需要更改,等有空重新写一个函数
解决的问题:
在编写完makefile文件后,在终端输入make命令进行编译,报错:*** 没有规则可制作目标“/xxx.c”,由“/xxx.o” 需求。 停止。
解决方案:空格替换Tab ; 成功运行 ;