用限定的运算符与结构实现一些功能,主要考察对位运算的了解,基本数据类型,浮点数,以及智商。
参考大佬1
参考大佬2
那个不用if的绝对值挺好的,据说可以加速绝对值计算,但是我测试并没有快多少>_<
int abs(int x)
{
int res=x>>31;
res=(x+res)^res;
return res;
}
有一些太复杂了不想想了,就直接抄大佬了。用的时候再补吧~
/*
* CS:APP Data Lab
*
*
* Id:P.H.S
* 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 header; it confuses the dlc
* compiler. You can still use printf for debugging without including
* , 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.
*/
/*
* 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)));
}
/*
* getByte - Extract byte n from word x
* Bytes numbered from 0 (LSB) to 3 (MSB)
* Examples: getByte(0x12345678,1) = 0x56
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 6
* Rating: 2
*/
int getByte(int x, int n) {
//移n没结果时要考虑移x
int tmp=(x>>(n<<3));
return tmp&0xff;
}
/*
* 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) {
int k=~(1<<31);
int t;
k=((k>>n)<<1)|1;//左移n-1位,n为0就右移一位
t=k&(x>>n);
return t;
}
/*
* bitCount - returns count of number of 1's in word
* Examples: bitCount(5) = 2, bitCount(7) = 3
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 40
* Rating: 4
*/
int bitCount(int x) {
/*抄的,完全没思路*/
int count;
int tmpMask1 = (0x55)|(0x55<<8);
int mask1 = (tmpMask1)|(tmpMask1<<16);
int tmpMask2 = (0x33)|(0x33<<8);
int mask2 = (tmpMask2)|(tmpMask2<<16);
int tmpMask3 = (0x0f)|(0x0f<<8);
int mask3 = (tmpMask3)|(tmpMask3<<16);
int mask4 = (0xff)|(0xff<<16);
int mask5 = (0xff)|(0xff<<8);
count = (x&mask1)+((x>>1)&mask1);
count = (count&mask2)+((count>>2)&mask2);
count = (count + (count >> 4)) & mask3;
count = (count + (count >> 8)) & mask4;
count = (count + (count >> 16)) & mask5;
return count;
/*抄网上的,我个人习惯lowbit写法,需要用while
while(x)
{
x-=(x&(-x));
k++;
}
*/
}
/*
* bang - Compute !x without using !
* Examples: bang(3) = 0, bang(0) = 1
* Legal ops: ~ & ^ | + << >>
* Max ops: 12
* Rating: 4
*/
int bang(int x) {
int t=(~x)+1;//只有0x00000000和0x80000000按位取反+1等于本身,xor后等于0
int k=(x>>31)&1;//区分0x00000000和0x80000000
return 1^((((t^x)>>31)&1)|k);
}
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return 1<<31;
}
/*
* fitsBits - return 1 if x can be represented as an
* n-bit, two's complement integer.
* 1 <= n <= 32
* Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int fitsBits(int x, int n) {//没懂题
n=32+(~n)+1;
return !(x^((x<>n));
/*先左移32-n位,在右移32-n位,即保留最后n位数。在与x异或
若两者相同表示x可被表示为一个n位整数,!0为1
*/
}
/*
* 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 m=x>>31;//x正数0x00000000,x负数0xffffffff
int k=(1<0);//(2^n)-1
x=x+(m&k);
return x>>n;
}
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
//补码取负
return (~x)+1;
}
/*
* isPositive - return 1 if x > 0, return 0 otherwise
* Example: isPositive(-1) = 0.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 8
* Rating: 3
*/
int isPositive(int x) {
return !((x>>31)|(!x));
}
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y) {
//先判符号,防止溢出,在做减法
int s1=(x>>31)&1;
int s2=(y>>31)&1;
int valid=s1^s2;
int res=y+(~x)+1;
return (((!(res>>31))&1)&(!valid))|(valid&(s1)&(!s2));
}
/*
* ilog2 - return floor(log base 2 of x), where x > 0
* Example: ilog2(16) = 4
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 90
* Rating: 4
*/
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;
}
/*
* float_neg - Return bit-level equivalent of expression -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_neg(unsigned uf) {
unsigned tmp=uf&(0x7fffffff);
unsigned res=uf^(0x80000000);
if(tmp>(0x7f800000)) res= uf;
return res;
}
/*
* 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) {
/*抄的,太难写了*/
unsigned shiftLeft=0;
unsigned afterShift, tmp, flag;
unsigned absX=x;
unsigned sign=0;
//special case
if (x==0) return 0;
//if x < 0, sign = 1000...,abs_x = -x
if (x<0)
{
sign=0x80000000;
absX=-x;
}
afterShift=absX;
//count shift_left and after_shift
while (1)
{
tmp=afterShift;
afterShift<<=1;
shiftLeft++;
if (tmp & 0x80000000) break;
}
if ((afterShift & 0x01ff)>0x0100)
flag=1;
else if ((afterShift & 0x03ff)==0x0300)
flag=1;
else
flag=0;
return sign + (afterShift>>9) + ((159-shiftLeft)<<23) + flag;
}
/*
* float_twice - Return bit-level equivalent of expression 2*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 representation of
* single-precision floating point values.
* When argument is NaN, return argument
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
unsigned float_twice(unsigned uf) {
unsigned f = uf;
if ((f & 0x7F800000) == 0) //指数是0,特殊小数
{
//左移一位
f = ((f & 0x007FFFFF) << 1) | (0x80000000 & f);
}
else if ((f & 0x7F800000) != 0x7F800000)//一般浮点数,直接加阶码
{
f =f + 0x00800000;
}
return f;//剩下NAN
}