/*
135. * bitAnd - x&y using only ~ and |
136. * Example: bitAnd(6, 5) = 4
137. * Legal ops: ~ |
138. * Max ops: 8
139. * Rating: 1
140. */
141.int bitAnd(int x, int y) {
142.
143. return ~(~x|~y);
144.}
这是第一个函数,看描述是要我们仅使用~和|实现&的功能。还记得离散数学上学的摩根定律吗,x&y = ~(~x|~y) ,所以第一个是比较简单的。
/*
146. * getByte - Extract byte n from word x
147. * Bytes numbered from 0 (LSB) to 3 (MSB)
148. * Examples: getByte(0x12345678,1) = 0x56
149. * Legal ops: ! ~ & ^ | + << >>
150. * Max ops: 6
151. * Rating: 2
152. */
153.int getByte(int x, int n) {
154.
155. return x>>(n<<3)&0xff;
156.
157.}
第二个函数,实现向返回第几字节的操作。需要知道的是两个数字占一个字节。而八个数字即是四个字节,双字。所以n只能从0到3取。第0位是最低位,例子里即是78,3为最高位,存的是12,以此类推。所以要返回第n位的数字,我们需要做的是右移挤掉比n低的数位,并且忽略掉比n高的数位。所以我们先做右移操作,需要注意的是移位的时候是按照二进制移位的,所以要先将n乘8,即n<<3,然后再右移。右移之后我们需要的数字就是最低位了,再和0xff做与运算,就可以把高位的数位全部忽略掉。
/*
159. * logicalShift - shift x to the right by n, using a logical shift
160. * Can assume that 0 <= n <= 31
161. * Examples: logicalShift(0x87654321,4) = 0x08765432
162. * Legal ops: ! ~ & ^ | + << >>
163. * Max ops: 20
164. * Rating: 3
165. */
166.int logicalShift(int x, int n) {
167.
168. return (x>>n)&(~((0x1<<31)>>n<<1));
169.}
第三个函数,实现逻辑右移。计算机在右移的时候会对有符号数进行算术右移(补齐最高有效位),对无符号数进行逻辑右移。这个函数要实现的是无条件的逻辑右移,也即我们需要做的是将右移的数与0x00…11做与运算,其中0的个数等同于右移位数。所以我们需要的是~(1<<31)>>n<<1[不能使用-号,所以不是n-1],所以结果是(x>>n)&(~(1<<31)>>n<<1).
/*
171. * bitCount - returns count of number of 1's in word
172. * Examples: bitCount(5) = 2, bitCount(7) = 3
173. * Legal ops: ! ~ & ^ | + << >>
174. * Max ops: 40
175. * Rating: 4
176. */
177. /*
178. **参考《CSAPP深入理解计算机系统》例3.50解答
179. */
180.int bitCount(int x) {
181. int c;
182. c=(x&0x55555555)+(x>>1&0x55555555);
183. c=(c&0x33333333)+(c>>2&0x33333333);
184. c=(c&0x0f0f0f0f)+(c>>4&0x0f0f0f0f);
185. c=(c&0x00ff00ff)+(c>>8&0x00ff00ff);
186. c=(c&0x0000ffff)+(c>>16&0x0000ffff);
187. return c
}
第四题要求返回二进制数中1的个数。参考深入理解3.50。我认为这个函数的难度较大,我参考了这个论坛的内容https://stackoverflow.com/questions/3815165/how-to-implement-bitcount-using-only-bitwise-operators。有兴趣的同学可以看一下,我觉得还是能看懂的
/*
195. * bang - Compute !x without using !
196. * Examples: bang(3) = 0, bang(0) = 1
197. * Legal ops: ~ & ^ | + << >>
198. * Max ops: 12
199. * Rating: 4
200. */
201./*
202.**If x!=0,x+(~x+1)=2^32,the highest bit of x and (~x+1)cannot be both 0(至少有一个为1再加上进位就可以继续进位,否则不会变成2^32).
203.*/
204.int bang(int x) {
205. return (~((x|(~x+1))>>31))&0x1;
206.}
x+~x+1 =2^32,当x不为0时,x和~x+1的最高位不可能同时为0。这个性质是我们解题的关键,我们只要将这两者做或运算,就能得到“x不为0时,最高位为1”和“x为0时,最高为为0“的性质,这时候我们再将结果右移31位,只保留最高位,再取反,与1做与运算就能得到我们想要的结果了。
```
/*
208. * tmin - return minimum two's complement integer
209. * Legal ops: ! ~ & ^ | + << >>
210. * Max ops: 4
211. * Rating: 1
212. */
213.int tmin(void) {
214. return 0x1<<31;
215.}
不多解释
/*
217. * fitsBits - return 1 if x can be represented as an
218. * n-bit, two's complement integer.
219. * 1 <= n <= 32
220. * Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
221. * Legal ops: ! ~ & ^ | + << >>
222. * Max ops: 15
223. * Rating: 2
224. */
225./* if all negative numbers(e.g x) are changed into ~x, all the numbers those
226. * can be represented as an n-bit, two's complement integer will be in range
227. * of 0~2^(n-1). If it was arithmatically shifted (n-1) bits to right, it'll
228. * be 0x00000000.
229. http://codejam.diandian.com/post/2011-04-16/427784
230.*/
231.int fitsBits(int x, int n) {
int shiftNumber= 32 + (~n + 1);// 32 - n
return !(x^((x<>shiftNumber));35.}
先左移32-n位,在右移32-n位,即保留最后n位数。在与x异或
若两者相同表示x可被表示为一个n位整数,!0为1
/*
237. * divpwr2 - Compute x/(2^n), for 0 <= n <= 30
238. * Round toward zero
239. * Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2
240. * Legal ops: ! ~ & ^ | + << >>
241. * Max ops: 15
242. * Rating: 2
243. */
244.int divpwr2(int x, int n) {
245. int sign=x>>31;
246. int bias=sign & ((1<0));
247. return (x+bias)>>n;
248.}
这个函数实现除以2^n的操作,如果x为正数直接移位,如果为负数,则加上偏置量后再移位。有关补码除法和偏置量的内容,详见深入理解
/*
250. * negate - return -x
251. * Example: negate(1) = -1.
252. * Legal ops: ! ~ & ^ | + << >>
253. * Max ops: 5
254. * Rating: 2
255. */
256.int negate(int x) {
257. return ~x+1;
258.}
补码+1即为相反数,有关补码内容强烈推荐看百度百科
/*
260. * isPositive - return 1 if x > 0, return 0 otherwise
261. * Example: isPositive(-1) = 0.
262. * Legal ops: ! ~ & ^ | + << >>
263. * Max ops: 8
264. * Rating: 3
265. */
266.int isPositive(int x) {
267. return !((x>>31)|(!x));
268.}
两种情况返回0 等于0 或者 小于0,所以返回标志位的非或者非0的非(0的标志位是0)
/*
270. * isLessOrEqual - if x <= y then return 1, else return 0
271. * Example: isLessOrEqual(4,5) = 1.
272. * Legal ops: ! ~ & ^ | + << >>
273. * Max ops: 24
274. * Rating: 3
275. */
276./* Because the substraction of two numbers with different signs may cause
277. * overflow, we should only judge whether x is negative then return
278. * 1(true). Otherwise we'll judge whether (x-y) is a non-positive
279. ((x+(~y)+1-1)>>31,which includes the situation of x-y=0)
280. * number and return 1(true).
281. reference:http://codejam.diandian.com/post/2011-04-16/427885
282.*/
283.int isLessOrEqual(int x, int y) {
284. int signx=x>>31;
285. int signy=y>>31;
286. int IsSameSign=(!(signx^signy));
287. return (IsSameSign & ((x+(~y))>>31)) | ((!IsSameSign) & signx);
288.}
比较大小,如果x是负,y是正就直接返回1,如果相同再做比较。所以设置一个IsSameSign,相同时,如果x<=y,则x-y<=0,那么x-y-1 < 0,故我们用x+~y再取其标志位就能得到想要的结果,如果不相同,那么只需要取x的标志位为1的情况即可。这两种情况或运算并起来即可
```
/*
290. * ilog2 - return floor(log base 2 of x), where x > 0
291. * Example: ilog2(16) = 4
292. * Legal ops: ! ~ & ^ | + << >>
293. * Max ops: 90
294. * Rating: 4
295. */
296. /* ilog2 is equivlance of finding the index of first 1 from left, the method is as following:
297. * check whether x's left half bits are all 0's, if so then throw them away,
298. * else right shift to reject the right half(remember the 16 bits thrown from
299. * right), to repeat it until only one "1" remaining and return the remembered
300. * number of x having been eliminated.
301. http://codejam.diandian.com/post/2011-04-16/428134
302. */
303.int ilog2(int x) {
int bitsNumber=0;
bitsNumber=(!!(x>>16))<<4;//
bitsNumber=bitsNumber+((!!(x>>(bitsNumber+8)))<<3);
bitsNumber=bitsNumber+((!!(x>>(bitsNumber+4)))<<2);
bitsNumber=bitsNumber+((!!(x>>(bitsNumber+2)))<<1);
bitsNumber=bitsNumber+(!!(x>>(bitsNumber+1)));
//for non zero bitsNumber, it should add 0
//for zero bitsNumber, it should subtract 1
bitsNumber=bitsNumber+(!!bitsNumber)+(~0)+(!(1^x));
//当x为0时,还需要减一才能得到正确值。
return bitsNumber;
/*
330. * float_neg - Return bit-level equivalent of expression -f for
331. * floating point argument f.
332. * Both the argument and result are passed as unsigned int's, but
333. * they are to be interpreted as the bit-level representations of
334. * single-precision floating point values.
335. * When argument is NaN, return argument.
336. * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
337. * Max ops: 10
338. * Rating: 2
339. */
340.unsigned float_neg(unsigned uf) {
341. unsigned result= uf ^ 0x80000000;//change the signed bit of uf
342. unsigned tmp=uf & 0x7fffffff;//change the signed bit of uf to 0
343. if( tmp > 0x7f800000 ) //When argument is NaN(exponent bits are all 1 and mantissa bits arenot all 0), return argument.
344. //IEEE754 standard:1 bit signed bit,8 bits exponent,23 bits mantissa.
345. result=uf;
346. return result;
347.}
348./*
将符号位改反即可,只需要多考虑NaN的情况即可,关于NaN,详见深入理解
* float_i2f - Return bit-level equivalent of expression (float) x
350. * Result is returned as unsigned int, but
351. * it is to be interpreted as the bit-level representation of a
352. * single-precision floating point values.
353. * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
354. * Max ops: 30
355. * Rating: 4
356. */
357.unsigned float_i2f(int x) {//Rounding is important!
358. unsigned sign=0,shiftleft=0,flag=0,tmp;
359. unsigned absx=x;
360. if( x==0 ) return 0;
361. if( x<0 ){
362. sign=0x80000000;
363. absx=-x;
364. }
365. while(1){//Shift until the highest bit equal to 1 in order to normalize the floating-point number
366. tmp=absx;
367. absx<<=1;
368. shiftleft++;
369. if( tmp&0x80000000 ) break;
370. }
371. if( (absx & 0x01ff) > 0x0100 ) flag=1;//***Rounding 1
372. if( (absx & 0x03ff) == 0x0300 ) flag=1;//***Rounding 2
373.
374. return sign+(absx>>9)+((159-shiftleft)<<23)+flag;
375.}
详见深入理解有关浮点数一章的讲解,仔细理解即可。
```
/*
377. * float_twice - Return bit-level equivalent of expression 2*f for
378. * floating point argument f.
379. * Both the argument and result are passed as unsigned int's, but
380. * they are to be interpreted as the bit-level representation of
381. * single-precision floating point values.
382. * When argument is NaN, return argument
383. * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
384. * Max ops: 30
385. * Rating: 4
386. */
387.unsigned float_twice(unsigned f) {
unsigned f = f;
if ((f & 0x7F800000) == 0) //
{
//左移一位
f = ((f & 0x007FFFFF) << 1) | (0x80000000 & f);
}
else if ((f & 0x7F800000) != 0x7F800000)
{
f =f + 0x00800000;
}
return f;
同上