这是一个关于机器级的整数、浮点数表示和位运算的实验。要求用给定的操作符、尽可能少的操作数去实现对应的函数功能。
完整的实验包:链接: https://pan.baidu.com/s/1xUBi3XDlidPQFNexbjXoLw 密码: 2333
以下是全部函数的代码:
1 /*****************************计算log2(x)向下取整*******************************/
2 int ilog2(int x) {
3 int bit_16, bit_8, bit_4, bit_2, bit_1;
4 bit_16 = (!!(x >> 16)) << 4; //如果x >> 16非零,则至少有16位
5 x = x >> bit_16;
6 bit_8 = (!!(x >> 8)) << 3;
7 x = x >> bit_8;
8 bit_4 = (!!(x >> 4)) << 2;
9 x = x >> bit_4;
10 bit_2 = (!!(x >> 2)) << 1;
11 x = x >> bit_2;
12 bit_1 = x >> 1; //还剩两位时,直接判断首位。bit_1 == 1,剩两位;bit_1 == 0,剩一位
13 return bit_16 + bit_8 + bit_4 + bit_2 + bit_1;
//实际是(bit_1 + 1)-1;由于向下舍入,总位数减一
14 }
15
16 /****************************表达x所需要的最少位数******************************/
17 int howManyBits(int x) {
18 int bit_16, bit_8, bit_4, bit_2, bit_1, result;
19 int k = x >> 31;
20 int temp = x ^ k;
//x为正,temp = x;x为负,temp = ~x
21 int isZero = (!!(temp << 31)) >> 31;
//x = 0或x = -1时,temp = 0,isZero = 0...0;否则isZero = 1...1
22 bit_16 = (!!(temp >> 16)) << 4;
23 temp = temp >> bit_16;
24 bit_8 = (!!(temp << 8)) << 3;
25 temp = temp >> bit_8;
26 bit_4 = (!!(temp << 4)) << 2;
27 temp = temp >> bit_4;
28 bit_2 = (!!(temp << 2)) << 1;
29 temp = temp >> bit_2;
30 bit_1 = temp >> 1;
31 result = bit_16 + bit_8 + bit_4 + bit_2 + bit_1 + 2;
//真正位数为bit_16 + ... + bit_1 + 1,再加符号位一位
32 return (!isZero) | (result & isZero);
33 }
34
35 /************************************逻辑右移*************************************/
36 int logicshift(int x, int n)
37 {
38 int temp = ~(1 << 31);
39 temp = ((temp >> n) << 1) + 1; //生成掩码0...01...1(前面为n个0)
40 return (x >> n) & temp;
41 }
42
43 /*************************类似于c语言中的x ? y : z**********************************/
44 int conditional(int x, int y,int z)
45 {
46 int temp = (~(!x)) + 1; //要在return中完成,必须生成x,y的掩码
47 return (temp & z) | ((~temp) & y); //当x = 0时,temp = 1...1;当x != 0时,temp = 0...0
48 }
49
50 /*********************************** x/ 2^n *****************************************/
51 int divpwr2(int x, int n)
52 {
53 int temp = (1 << n) + (~0); //temp为baising(偏置),1...1(共n个1)
54 return (x + ((x >> 31) & temp)) >> n; //只有负数才要加偏置,所以temp要与符号位相与
55 }
56
57 /****************************** x < y ? ***********************************/
58 int isLessOrEqual(int x, int y)
59 {
60 int signx = x >> 31;
61 int signy = y >> 31;
62 int signEqual = (!(signx ^ signy) & ((x + (~y)) >> 31));//符号位不同时,做差
63 int signDiffer = signx & (!signy); //符号位相同,直接比较符号位
64 return signEqual | signDiffer;
65 }
66
67 /**********************操作数更小的版本**************************/
68 int isLessOrEqual_2(int x, int y)
69 {
70 int not_y = ~y;
71 return ((((x + not_y) & (x ^ not_y)) | (x & not_y)) >> 31) & 1;
72 // x-y-1<0 <----------x,y不同号------>x为负,y为正,才为正
73 }
74
75 /****************************不用负号得到-x*********************************/
76 int negate(int x)
77 {
78 return ~x + 1; //按位取反,末位加一
79 }
80
81 /**********************返回最小的补码***************************************/
82 int tmin(void)
83 {
84 return 1 << 31;
85 }
86
87 /*************************只用~ 和 | 实现x&y*****************************/
88 int bitAnd(int x, int y)
89 {
90 return ~(~x | y); //摩根律
91 }
92
93 /**************************从字x中取出第n个字节*********************************/
94 int getByte(int x, int n)
95 {
96 return (x >> (n << 3)) & 0xff; //是从0开始数的
97 }
98
99 /*********************************计算x中1的数目*********************************/
100 int bitCount(int x)
101 {
102 int result;
103 int tmpmark1 = 0x55 + (0x55 << 8); //最大0xff
104 int mark1 = tmpmark1 + (tmpmark1 << 16);
105 int tmpmark2 = 0x33 + (0x33 <<8);
106 int mark2 = tmpmark2 + (tmpmark2 << 16);
107 int tmpmark3 = 0x0f + (0x0f << 8);
108 int mark3 = tmpmark3 + (tmpmark3 << 16);
109 int mark4 = 0xff + (0xff << 16);
110 int mark5 = 0xff + (0xff << 8); //以上生成5个掩码
111
112 result = (x & mark1) + ((x >> 1) & mark1);
113 result = (result & mark2) + ((result >> 2) & mark2); //这两个由于进位问题,不能先加再与
114 result = (result + (result >> 4)) & mark3; //分治
115 result = (result + (result >> 8)) & mark4;
116 result = (result + (result >> 16)) & mark5;
117 return result;
118 }
119
120 /***************************计算uf/2*********************************/
121 unsigned float_half(unsigned uf)
122 {
123 unsigned s = uf & 0x80000000;
124 unsigned exp = uf & 0x7f800000;
125 int lsb = ((uf & 3) == 3); //判断frac最后两位是否为11
126 if (exp == 0x7f800000)
127 return uf;
128 else if (exp <= 0x800000)
129 return s | (((uf ^ s) + lsb) >> 1); //uf^s将符号位置零,uf^s = frac + exp末位
130 else
131 return uf - 0x800000; //整体思路就是模拟
132 }
133
134 /****************************计算(float)x***********************************/
135 int float_f2i(unsigned uf)
136 {
137 int abs;
138 int sign = uf >> 31;
139 int exp = (uf >> 23) & 0xff;
140 int frac = uf & 0x007fffff;
141 if (exp < 0x7f) return 0;
142 if (exp > 157) return 0x80000000; //Tmax = 2^31 -1
143
144 abs = ((frac >> 23) + 1) << (exp - 127); //模拟
145 if (sign)
146 return -abs;
147 else
148 return abs;
149 }
150
151 /****************************计算2*f***************************************/
152 unsigned float_twice(unsigned uf)
153 {
154 int result;
155 int exp = uf & 0x7f800000;
156 int frac = uf & 0x7fffff;
157 if (exp == 0x7f800000)
158 return uf;
159 else if (exp == 0)
160 frac = frac << 1; //frac也可用uf代替,因为此时frac = uf
161 else
162 exp = exp + 0x800000;
163 result = (uf & 0x80000000) | exp | frac;
164 return result;
165 }
个性签名:时间会解决一切