这可能是CDSN最良心的CSAP_label1了

学生狗,在学CSAP,做完label1肝得要吐血(滑稽.jpg)
之前上网发现CDSN好像还没解释的很详细的label1
自己就把实验报告贴出来吧

由于离ddl还差几天(滑稽.jpg)
柴云鹏老师的学生,你们是我的同班同学欧
乌拉!

先贴源代码`/*

  • CS:APP Data Lab
  • bits.c - Source file with your solutions to the Lab.
  •      This is the file you will hand in to your instructor.
    
  • WARNING: Do not include the <stdio.h> header; it confuses the dlc
  • compiler. You can still use printf for debugging without including
  • <stdio.h>, although you might get a compiler warning. In general,
  • it’s not good practice to ignore compiler warnings, but in this
  • case it’s OK.
    */

#if 0
/*

  • Instructions to Students:
  • STEP 1: Read the following instructions carefully.
    */

You will provide your solution to the Data Lab by
editing the collection of functions in this source file.

INTEGER CODING RULES:

Replace the “return” statement in each function with one
or more lines of C code that implements the function. Your code
must conform to the following style:

int Funct(arg1, arg2, …) {
/* brief description of how your implementation works */
int var1 = Expr1;

int varM = ExprM;

  varJ = ExprJ;
  ...
  varN = ExprN;
  return ExprR;

}

Each “Expr” is an expression using ONLY the following:

  1. Integer constants 0 through 255 (0xFF), inclusive. You are
    not allowed to use big constants such as 0xffffffff.
  2. Function arguments and local variables (no global variables).
  3. Unary integer operations ! ~
  4. Binary integer operations & ^ | + << >>

Some of the problems restrict the set of allowed operators even further.
Each “Expr” may consist of multiple operators. You are not restricted to
one operator per line.

You are expressly forbidden to:

  1. Use any control constructs such as if, do, while, for, switch, etc.
  2. Define or use any macros.
  3. Define any additional functions in this file.
  4. Call any functions.
  5. Use any other operations, such as &&, ||, -, or ?:
  6. Use any form of casting.
  7. Use any data type other than int. This implies that you
    cannot use arrays, structs, or unions.

You may assume that your machine:

  1. Uses 2s complement, 32-bit representations of integers.
  2. Performs right shifts arithmetically.
  3. Has unpredictable behavior when shifting an integer by more
    than the word size.

EXAMPLES OF ACCEPTABLE CODING STYLE:
/*

  • pow2plus1 - returns 2^x + 1, where 0 <= x <= 31
    /
    int pow2plus1(int x) {
    /
    exploit ability of shifts to compute powers of 2 */
    return (1 << x) + 1;
    }

/*

  • pow2plus4 - returns 2^x + 4, where 0 <= x <= 31
    /
    int pow2plus4(int x) {
    /
    exploit ability of shifts to compute powers of 2 */
    int result = (1 << x);
    result += 4;
    return result;
    }

FLOATING POINT CODING RULES

For the problems that require you to implent floating-point operations,
the coding rules are less strict. You are allowed to use looping and
conditional control. You are allowed to use both ints and unsigneds.
You can use arbitrary integer and unsigned constants.

You are expressly forbidden to:

  1. Define or use any macros.
  2. Define any additional functions in this file.
  3. Call any functions.
  4. Use any form of casting.
  5. Use any data type other than int or unsigned. This means that you
    cannot use arrays, structs, or unions.
  6. Use any floating point data types, operations, or constants.

NOTES:

  1. Use the dlc (data lab checker) compiler (described in the handout) to
    check the legality of your solutions.
  2. Each function has a maximum number of operators (! ~ & ^ | + << >>)
    that you are allowed to use for your implementation of the function.
    The max operator count is checked by dlc. Note that ‘=’ is not
    counted; you may use as many of these as you want without penalty.
  3. Use the btest test harness to check your functions for correctness.
  4. Use the BDD checker to formally verify your functions
  5. The maximum number of ops for each function is given in the
    header comment for each function. If there are any inconsistencies
    between the maximum ops in the writeup and in this file, consider
    this file the authoritative source.

/*

  • STEP 2: Modify the following functions according the coding rules.
  • IMPORTANT. TO AVOID GRADING SURPRISES:
    1. Use the dlc compiler to check that your solutions conform
  •  to the coding rules.
    
    1. Use the BDD checker to formally verify that your solutions produce
  •  the correct answers.
    

*/

#endif
/* Copyright © 1991-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.

The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
http://www.gnu.org/licenses/. /
/
This header is separate from features.h so that the compiler can
include it implicitly at the start of every compilation. It must
not itself include <features.h> or any other header that includes
<features.h> because the implicit include comes before any feature
test macros that may be defined in a source file before it first
explicitly includes a system header. GCC knows the name of this
header in order to preinclude it. /
/
We do support the IEC 559 math functionality, real and complex. /
/
wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
Unicode 6.0. /
/
We do not support C11 <threads.h>. /
//Rating:1
/

  • bitAnd - x&y using only ~ and |
  • Example: bitAnd(6, 5) = 4
  • Legal ops: ~ |
  • Max ops: 8
  • Rating: 1
    /
    int bitAnd(int x, int y) {
    return ((x)|(~y)) ;
    }
    /
  • evenBits - return word with all even-numbered bits set to 1
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 8
  • Rating: 1
    /
    int evenBits(void) {
    int x = 85 ;
    int y = (x<<8) ;
    x = x|y ;
    y = (x<<16) ;
    x = x|y ;
    //printf("%x",x) ;
    return x;
    }
    /
  • fitsShort - return 1 if x can be represented as a
  • 16-bit, two’s complement integer.
  • Examples: fitsShort(33000) = 0, fitsShort(-32768) = 1
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 8
  • Rating: 1
    */
    int fitsShort(int x) {
    int y = x >> 15;
    return !( (y >> 16) ^ y);
//int a = (x>>15)<<16 ;
//printf("%x\n",a) ;
//现在的思路已知了如果a  = ffff0000 ;或者a = 0 ; 
//那么这个就可以b表示
//关键问题处在输出上
//如何用两个操作符聪明的输出?
//return !(a>>16+1) 

}
/*

  • isTmax - returns 1 if x is the maximum, two’s complement number,

  • and 0 otherwise 
    
  • Legal ops: ! ~ & ^ | +

  • Max ops: 10

  • Rating: 1
    /
    int isTmax(int x) {
    /int a ;
    a = 1 ;
    a = a<<31 ;//现在a是min
    //printf("%d\n",a) ;
    return !(a+x+1) ;
    /
    int y=(x+1);
    return (!(y+y))^(!~x);
    }
    /

  • minusOne - return a value of -1

  • Legal ops: ! ~ & ^ | + << >>

  • Max ops: 2

  • Rating: 1
    /
    int minusOne(void) {
    return ~0 ;
    }
    /

  • upperBits - pads n upper bits with 1’s

  • You may assume 0 <= n <= 32

  • Example: upperBits(4) = 0xF0000000

  • Legal ops: ! ~ & ^ | + << >>

  • Max ops: 10

  • Rating: 1
    */
    int upperBits(int n) {

    return ((!!n)<<31)>>(n+(~0)) ;
    //return (0&(!n+(0)))<<(32+(~n+1)) ;
    /*int a ;
    a = ~0 ;
    //printf("%x\n",a) ;
    int b ;
    b = ~n+1 ;//b = -n ;
    // printf("%d",b) ;
    b = 32 + b ;
    return ((a>>b)<<b) ; /
    }
    //Rating:2
    /

  • allEvenBits - return 1 if all even-numbered bits in word set to 1

  • Examples allEvenBits(0xFFFFFFFE) = 0, allEvenBits(0x55555555) = 1

  • Legal ops: ! ~ & ^ | + << >>

  • Max ops: 12

  • Rating: 2
    */
    int allEvenBits(int x) {
    int y ;

y = 0xAA ;
y = y|y<<8 ;
y = y|y<<16 ;
return !~(x|y) ;	 

}
/*

  • byteSwap - swaps the nth byte and the mth byte
  • Examples: byteSwap(0x12345678, 1, 3) = 0x56341278
  •        byteSwap(0xDEADBEEF, 0, 2) = 0xDEEFBEAD
    
  • You may assume that 0 <= n <= 3, 0 <= m <= 3
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 25
  • Rating: 2
    /
    int byteSwap(int x, int n, int m) {//sladk;lskdlaskdl;askdlaskdlaskdlskalfkjsakljfklasjfaksjf;lasjlfaksfl;askf;las
    //unsigned int a = x ;
    int nn = n << 3;
    int mm = m << 3;
    int p = ( ( x >> mm ) ^ ( x >> nn) ) & 0xFF;
    return x ^ ( ( p << mm) | ( p << nn) );
    }
    /
  • copyLSB - set all bits of result to least significant bit of x
  • Example: copyLSB(5) = 0xFFFFFFFF, copyLSB(6) = 0x00000000
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 5
  • Rating: 2
    /
    int copyLSB(int x) {
    return ((x<<31)>>31) ;
    }
    /
  • divpwr2 - Compute x/(2^n), for 0 <= n <= 30
  • Round toward zero
  • Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 15
  • Rating: 2
    */
    int divpwr2(int x, int n) {
int y = (x>>31) ;
x += y&((1<<n)+~0) ;
x=x>>n ;
return x ;

/*int y = (x>>31) ;
//得到原码
x = (x+y)^y ;

x = x>>n ;
//printf("%d ",x) ;
//printf("%d ",y) ;
x = (x^y) + (1&y) ;
return x  ;*/

}
/*

  • leastBitPos - return a mask that marks the position of the
  •           least significant 1 bit. If x == 0, return 0
    
  • Example: leastBitPos(96) = 0x20
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 6
  • Rating: 2
    /
    int leastBitPos(int x) {
    return (~x+1)&x ;
    }
    /
  • oddBits - return word with all odd-numbered bits set to 1
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 8
  • Rating: 2
    /
    int oddBits(void) {
    int x = 170 ;
    x = x|(x<<8) ;
    x = x|(x<<16) ;
    //printf("%x",x) ;
    return x;
    }
    //Rating:3
    /
  • bitMask - Generate a mask consisting of all 1’s
  • lowbit and highbit
  • Examples: bitMask(5,3) = 0x38
  • Assume 0 <= lowbit <= 31, and 0 <= highbit <= 31
  • If lowbit > highbit, then mask should be all 0’s
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 16
  • Rating: 3
    */
    int bitMask(int highbit, int lowbit) {//zxclzkxlc;zk;xlckzx;lkcl;zxkc;lzxkcl;zxkcl;zxkcl;zxkcl;zxkcl;zxkcz
    int i=~0;
    return (((i << highbit) << 1) ^ (i << lowbit)) & (i << lowbit);
/*int x = ~0 ;
//set low boundry ;
int y = (x<<lowbit) ;
//printf("%x\n",y) ;
//set height boundry ;
unsigned z = x ;
int cc = (~highbit)+32 ;

z = (z>>cc) ;
// printf("%x\n",z) ;
return y&z ;*/

}
/*

  • isLess - if x < y then return 1, else return 0
  • Example: isLess(4,5) = 1.
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 24
  • Rating: 3
    */
    int isLess(int x, int y) {
    int z=~y;
    return (((x+z+1)&(x^z)|(x&z))>>31)&0x1;

/*int y1 = ((y>>31)<<31) ;
//printf("%x\n",y1) ;
int y2 = ~y1 ;
//printf("%x\n",y2) ;
y = y^y2 ;

y +=1 ;
y += y1 ; 
//printf("%d\n",y) ;

int  z  = x+y ;
unsigned z1 = z ;
return (z1>>31) ;*/

}
/*

  • logicalShift - shift x to the right by n, using a logical shift
  • Can assume that 0 <= n <= 31
  • Examples: logicalShift(0x87654321,4) = 0x08765432
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 20
  • Rating: 3
    */
    int logicalShift(int x, int n) {

// x>>n ;
// int y = (x<<1) ;
//printf("%x\n",y1) ;
//rintf("%x\n",(x<<n)) ;
int y1 = (((x>>31)<<31)>>(n))<<1 ;

return (x>>(n))^y1 ;

}
/*

  • satMul2 - multiplies by 2, saturating to Tmin or Tmax if overflow
  • Examples: satMul2(0x30000000) = 0x60000000
  •         satMul2(0x40000000) = 0x7FFFFFFF (saturate to TMax)
    
  •         satMul2(0x80000000) = 0x80000000 (saturate to TMin)
    
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 20
  • Rating: 3
    /
    int satMul2(int x) {
    int a=x<<1;
    int b=a>>31;
    int c=(x^a)>>31;
    int tmin=1<<31;
    return ((~c)&a)+(c&(b+tmin)) ;
    }
    /
  • 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 ;
    int m = y ;
    y = (~y)+1 ;
    z = x+y ;
    //printf("%x\n",z) ;
    z = (zx)&(mx) ;
    //printf("%x\n",z) ;
    //unsigned k = z ;
    //printf("%x\n",!(k>>31)) ;
    return !((z>>31)&1) ;

}
//Rating:4
/*

  • bang - Compute !x without using !
  • Examples: bang(3) = 0, bang(0) = 1
  • Legal ops: ~ & ^ | + << >>
  • Max ops: 12
  • Rating: 4
    /
    int bang(int x) {
    int y = ((x)&((x+(0)))) ;
    return (y>>31)&1 ;
    }
    /
  • bitParity - returns 1 if x contains an odd number of 0’s
  • Examples: bitParity(5) = 0, bitParity(7) = 1
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 20
  • Rating: 4
    /
    int bitParity(int x) {
    x = x^(x>>16) ;
    x = x^(x>>8) ;
    x = x^(x>>4) ;
    x = x^(x>>2) ;
    x = x^(x>>1) ;
    //unsigned k = x ;
    return x&1 ;
    }
    /
  • isPower2 - returns 1 if x is a power of 2, and 0 otherwise
  • Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0
  • Note that no negative number is a power of 2.
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 20
  • Rating: 4
    /
    int isPower2(int x) {
    return !(((x&(~x+1))^x)|(!x)|(x>>31));
    }
    //Extra
    /
  • float_i2f - Return bit-level equivalent of expression (float) x
  • Result is returned as unsigned int, but
  • it is to be interpreted as the bit-level representation of a
  • single-precision floating point values.
  • Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
  • Max ops: 30
  • Rating: 4
    /
    unsigned float_i2f(int x) {
    return 2;
    }
    /
  • leftBitCount - returns count of number of consective 1’s in
  • left-hand (most significant) end of word.
    
  • Examples: leftBitCount(-1) = 32, leftBitCount(0xFFF0F0F0) = 12
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 50
  • Rating: 4
    */
    int leftBitCount(int x) {
    return 2;
    }`

之后是我写实验报告:所有程序都跑过了,经得起测试
第一题:bitAnd
如果使用&操作,那么1&1 = 1 ;
其他的情况都是零
但是如果使用或操作,那么0|0 = 0
其他的三种情况都是1
我们先用~把传入的两个数字取反
则之前的 1变成了0
再将两个数|一下
只有之前两个数全是一个二进制位再操作之后表现为0
其余二进制位表现为1
通过对新得到的二进制串取反操作得到正确结果
代码为: return ((x)|(~y)) ;
第二题 :eventbit
这里的要求是偶数位都是1
已知
1.二进制串的计数是从零开始
2.只能够使用255之内的整数
先构建出01010101的八位(十进制是85)
之后右移八位,并|自身
再右移16位|上一步的结果
的到来所要求的函数值
代码为
:int x = 85 ;
int y = (x<<8) ;
x = x|y ;
y = (x<<16) ;
x = x|y ;
//printf("%x",x) ;
return x;
第三题:fitsShort
题目要求判断这个三十二位的二进制数是否能够用十六位的二进制数表示出来
首先明确:
三十二位的二进制数是有1个符号位和三十一个有效位
十六位的二进制数是有1个符号位和十五个二进制位
那么问题就变成了:
如何将三十一位压缩成十五位
对于正数而言:这代表着31到十六位都是0
对于负数而言:这代表着31到十六位都是一(这样负数才足够大 ,大到能够表示)
先将x>>15
将所有的有效位去掉
如果能够压缩,剩下的数字应该出来符号位之外不包含任何信息
负数
0xffff(不确定)【全是 1的时候可以表示】
正数(和0)
0x0000(不确定)【全是0的时候可以表示】
利用整数右移的技巧
如果可以表示,则(x>>15)>>16 = x>>15
其他情况不能表示
利用异或判断相等关系
代码为
int y = x >> 15;
return !( (y >> 16) ^ y);
第四题:ismax
题目要求判断一个数是否是最大值
三十二位机的十六进制表达式是0x7fffffff
如果这max+1就会发生溢出,溢出成为最小的负数
0x80000000
由溢出的性质,又可得
0x80000000+0x8000000 = 0
基本完成
但如果传入的是-1,也会得到相同的结果
所以我们要排除-1,这个操作就算成功了
由-1取反得0的性质可以排除-1
代码如下:
int y=(x+1);
return (!(y+y))^(!~x);
第五题:minusOne
本题目的是得到-1
由于-1不在0~255之内,所以不被允许直接声明

先分析-1的二进制串的形式
:11111111111111111111111111111111
不难发现,如果将-1取反,的得到的是0
0是可以直接被声明的
代码:
Return ~0 ;
第六题: upperbits(int n)
题目要求:
将数字的前n个二进制位设置为1
传入0 的时候结果会是零
为了减少分类讨论,我们要做到把零和非零的数并行操作
使用!!N
作为要操作的基准数
如果传入的不是零 这个基准数变成了1
如果是零 ,则变成了 0 (怎么操作结果都会为零)
先将!!N<<31
使得其位于最顶端
之后右移n-1位
由上题可知~0 = -1 ;
源代码:
return ((!!n)<<31)>>(n+(~0)) ;
第七题:allEvenBits(int x)
题目要求:要判断是否所有的偶数位全是1
利用^操作符
先令y = 0x(AA)(也就是10101010)
就像第二题那样将将这个八位的特征扩展到三十位
y = y|y<<8 ;
y = y|y<<16 ;
通过^进行比较
源代码:
y = 0xAA ;
y = y|y<<8 ;
y = y|y<<16 ;
return !~(x|y) ;
第八题:bitswap(int x ,int n ,int m)
题目要求:将第m和第n个字节交换
首先:将m,和n分别扩展到原来的 八倍,代表一个个比特的顺序
其次
将该数字的第m个字节移动到最低有效位ing几率
对第n个字节进行同样操作
这两者异或,最低八位就m^n(指的是字节的内容)
利用异或的性质发现规律:
Mnm = n ;
Mnn = m ;
并0^a = a

先将m^n的前二十四位清除
再将m^n移动到第m个字节,与之进行异或
同理对于第n个字节进行操作
源代码:
int nn = n << 3;
int mm = m << 3;
int p = ( ( x >> mm ) ^ ( x >> nn) ) & 0xFF;
return x ^ ( ( p << mm) | ( p << nn) );
第九题:copyLSB(int x)
题目要求:将这个整数的所有二进制位都置为最低的哪那一位
可以利用整数右移的格式:
如果第一位是1,那么右移之后左边全部补1
则要先将最低为的那个数值放到最高位
在这个过程中其他数据全部被清洗掉了
并且右边三十一位全部是1
之后利用整数右移的格式右移三十一位
源代码:
return ((x<<31)>>31) ;
第十题:divpwr2(int x, int n)
题目要求:
求得x/2^n
并且向0取整
难点分析
如果暴力直接右移
如果正数是向0取整
如果x是负数切不被整除
负数后三十一位的某项会被舍弃
但是负数后三十一位某一位有值代表的意义是一个正数
这会导致直接暴力右移对于负数而言是向-∞取整
解题思路
通过上面的分析,可以得到难点是负数上
我们可以通过对于负数+2^n-1的方式得到解决
这样只要负数(二进制)的后n位不全是零,那么就可以通过进位向0取整
下一个问题是:正数和负数要并行运算
我们可以通过扩大符号影响的方式来实现
N = x>>31
如果是正数这是0
0&任何数是0
对于负数这是-1
-1&任何数是任何数本身
经过分析发现,可以通过运用N的方式使得负数增加一个数在处理,而正数直接处理
源代码:
int y = (x>>31) ;
x += y&((1<<n)+~0) ;
x=x>>n ;
return x ;
第十一题:leastBitPos(int x)
题目要求:
返回一个面具,这个面具从右往左数第一个1的位置和传进来的x的第一个1的位置相等,并且其他位置全是零
如果x是零,那么这个面具也就是0
解题思路:
从右往左数第一个1的性质就是其右边全是零,并且这个位置是1
这个特殊的性质很难判断
我们不妨取反
那就变成了
这个位置自己是0
这个位置的右边所有位置都是1
这样+1之后这个位置变成1,这个位置右边变成0成为了这状态的特有性质
我们发现,只有这个位置在取反加一之后和之前都是1
则可以返回(~x+1)&x
源代码:
return (~x+1)&x ;
第十二题:oddBits(void)
题目要求
要求返回一个使奇数位置全为1,其他位置全为0的数字
思路:
和第二题一样的傻瓜方法
先声明一个数字满足这种性质
之后做两次左移+|操作
代码:
int x = 170 ;
x = x|(x<<8) ;
x = x|(x<<16) ;
//printf("%x",x) ;
return x;
第十三题:bitMask(int highbit, int lowbit)
题目要求:
获得一个面具
这个面具在最高位和最低位之间为1
其余的地方为0
Low>height的时候为0
总体思路:
获得大断1的方式有两种
首先是先将1移动到最高位之火再右移
其次是先通过~0获得一个0xffffffff之后进行左移
当然第一种方式也能偶完成这个函数要完成的工作,我们不妨先选择我比较习惯的第二种方式
首先得到一个0xfffff记为a
之后将a左移low位得到b
再将a左移height+1位得到c
对于b和c而言
只有在low和hight中间区域(包括两个数本身)的区域是不一致的
我们简单的做一个异或操作
可以得到自己的面具
另一个问题:
如果这样操作,low>height的时候这个面具不是0
解决方案:
我可以且上一个a<<low
这样有效的在low过大的时候把面具中所有的1都清楚掉
源代码:
int i=~0;
return (((i << highbit) << 1) ^ (i << lowbit)) & (i << lowbit);
第十四题:isLess(int x, int y)
题目要求:
判断x<y是否成立
思路:
X<y一般会有三种情况
X < 0 ,Y<0 X-y>0
X>0, Y>0 x-y<0 ;
X<0 ,Y>0
因为会有减法出现,先将y取反
Z = ~y ;
可以得到一个显而易见的结果:
(x&z) 得最高位= 1 ; x = z =1的时候
或者(x+z+1 ^ x得最高位为1 x!=z的时候
则表达式为
return (((x+z+1)&(x^z)|(x&z))>>31)&0x1;
源代码为:
int z=~y;
return (((x+z+1)&(x^z)|(x&z))>>31)&0x1;
第十五题:logicalShift(int x, int n)
题目要求:
实现逻辑右移:
思路:
面对的主要问题:
要对负数右移时候补足的1进行消除
同时由于要和正数进行并行操作
这部分的实现必须借助正负数不同的部分(符号位)
先通过右移三十一位在左移三十一位的方式得到位于最左端的 符号位y
利用整形的规则将x>>n
之后将y>>n-1;
这里要注意:如果n = 0 的时候会右移-1,也就是31位,这心啊然不是我们想要看到的
这一部分的操作可以优化(y>>n)<<1
并没有增加操作符号的数量
此时
如果是负数,则y的前n位是1
如果是正数,则y的前n 位值0
而后面的都是0, 0^anything = anything
则可以聪明的通过异或
将负数的多余的1消除
没有影响正数
没有对结果产生影响
源代码:
int y1 = (((x>>31)<<31)>>(n))<<1 ;
return (x>>(n))^y1 ;
第十六题:int satMul2(int x)
题目其要求:
将一个数字乘二
如果溢出则取Tmax或者Tmin
解题思路:
什么样的数字*2之后会溢出?
显然这个数字的第三十二位和第三十一位不相同的数字
解决了这个问题,我们面对的第二个问题就是:
如何让溢出和不溢出的数字并行计算?
答案是通过问题一的特征去处理着啦你各种情况:
如果这两者不同
进行什么操作
如果这两者相同
进行什么操作
在没有分支语句的时候,最好的办法就是预先计算出这两个数字
通过& + 和 |操作在一种情况发生的时候将另一种情况设置为0
PS:面对分支的时候还有一种方案
就是把所有的情况用& 和|谅解
通过设置c& + ~c&
使得每个值在不同情况下或等于零或等于其他分支
不过那多用于分支的一种情况内部有不同的方式实现
或者我们要排除掉这个中间的几个不成立的几个特殊情况
我们要面对的第三个问题就是:
如何判断溢出的应该是正无穷还是负无穷
这个问题的解决方案应该是通过提取原始数据符号位来进行并行操作的
三个主要的问题解决完了:
显然可以得到
int a=x<<1;
//使得第一个问题中说的第二位移动到第一位上
int b=a>>31;
//将这个东西右三十一位
这里用了一小技巧
因为溢出的时候,这个探讨到底是一处到正无穷还是负无穷的量才派上用场
但是溢出的时候第二位和第一位恰好相反
这里这个数字的提取而不是第一位的提取在后面为我们节省下了一个宝贵的操作符
int c=(x^a)>>31;
//比较第二位和第一位是否相等,并将其扩大到三十二位从而常委判断标准(对应问题2)
int tmin=1<<31;
//得到一个tim的函数值
性质:tmin + 0xffffffff = tmax ;
这里就用到了上述的小技巧:
正数溢出是得到最大的正数
得到最大的正数代表要 通过符号位得到一个tmin
但是正数的符号位是0所以只能够得到一个0,
需要取反得到0xffffffff,
但是由于这个时候(已知溢出)
由问题1可知是在这个时候第一位和第二位是相反的
于是直接通过第二部的小trick来使得自己能够生一个操作符
return ((~c)&a)+(c&(b+tmin)) ;
代码:
int a=x<<1;
int b=a>>31;
int c=(x^a)>>31;
int tmin=1<<31;
return ((~c)&a)+(c&(b+tmin)) ;
第十七题 : subOK(int x, int y)
题目要求:
判断两个函数相减是否会溢出
思路分析
第一个问题:
什么样的数相减会溢出:
X>0 ; y<0
X<0 , y>0
第二个问题:
如果这两个数字溢出,会发生什么
正 + 正 = 负
负 + 负 = 正
解决了这两个问题
Z = x-y ;
(xy)&(xz)

31 &1
Return !
代码:
int z ;
int m = y ;
y = (~y)+1 ;
z = x+y ;
//printf("%x\n",z) ;
z = (zx)&(mx) ;
//printf("%x\n",z) ;
//unsigned k = z ;
//printf("%x\n",!(k>>31)) ;
return !((z>>31)&1) ;

第十八题:int bang(int x)
题目:
实现!的功能
同时不要使用!
这种一种情况存在不确定个1,另一种情况不存在1的问题
我们可以通过判断是否进位的方式实现:(
如同之前的第十题:
除二,
向零取整)
判断是否 要进位
分类讨论:
最高层为就应该返回0
最高层不为1
加上0xffffff看是否会进位
代码:
int y = ((x)&((x+(0)))) ;
return (y>>31)&1 ;

第十九题目:bitParity(int x)
题意:
判断这数中的1是奇数还是偶数
思路:将这个数字分两半之后进行异或操作
异或操作完成之后再将结果(十六位)进行异或操作
得到结果
偶数数字会被消去
如果剩下1,代表有奇数个1
反之,是偶数个

第二十题: isPower2(int x)
题意:判断这个数是不是二的倍数
思路:
先排除负数,再排除零
挣下的只有正数了
对于这些正数,想到之前写的函数:
Least pos
那么先通过(x&(~x+1))得到面具
符合本提要求的 函数值和面具相等
return !(((x&(~x+1))^x)|(!x)|(x>>31));

猜你喜欢

转载自blog.csdn.net/weixin_42222917/article/details/83154014