Datalab: 人类智慧

unsigned intint部分基本都是人类智慧,而float则都是最基本的概念,导致这一部分的区分度几乎为0.

bitXor

xor操作的本质实际上是找到\(x\)\(y\)中不同的位置,那么实际上只需要把\(x\)和~\(y \ \&\)一下,就可以找到x中为\(1\)\(y\)中为\(0\)的位置,同理可以找到\(x\)中为\(0\)\(y\)中为\(1\)的位置,再 or 一下就变成了答案,而or可以用~和and 表示。

/*
 * bitXor - x^y using only ~ and &
 *   Example: bitXor(4, 5) = 1
 *   Legal ops: ~ &
 *   Max ops: 14
 *   Rating: 1
 */
int bitXor(int x, int y)
{
  return ~((~((~x) & y)) & (~((~y) & x)));
}

tmin

补码可以表示的最小数就是0x80000000,实际上也就是\(1<<31\)

/*
 * tmin - return minimum two's complement integer
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void)
{
  return (1 << 31);
}

isTmax

只需要判断一个数是不是0x7fffffff,首先我们思考 \(x \ xor\ x+1\) 后的结果,发现还有一个反例,那就是\(-1\),然后单独判断一下\(-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){
  return !((!(~x)) | (~(x ^ (x + 1))));
}

allOddBits

我们可以直接构造一个all Odd Bits,且仅有all Odd bits.
然后判断一下结果即可。

/*
 * allOddBits - return 1 if all odd-numbered bits in word set to 1
 *   where bits are numbered from 0 (least significant) to 31 (most significant)
 *   Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2
 */
int allOddBits(int x)
{
  int cont = 0xaa;
  cont = cont | (cont << 8) ;
  cont = cont | (cont << 16) ;
  return !((~x)&cont);
}

negate

-x = ~x + 1

/*
 * negate - return -x
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x)
{
  return (~x) + 1;
}

isAsciiDigit

/*
 * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
 *   Example: isAsciiDigit(0x35) = 1.
 *            isAsciiDigit(0x3a) = 0.
 *            isAsciiDigit(0x05) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 3
 */
int isAsciiDigit(int x)
{
  int pre = x >> 4, lst = x & 0xf, mi3 = ((~3)+1);
  int chk = 9 + ((~lst) + 1);
  return (!(pre + mi3)) & (!(chk &(1<<31)));
}

conditional

/*
 * conditional - same as x ? y : z
 *   Example: conditional(2,4,5) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3
 */
int conditional(int x, int y, int z)
{
  int ans = 0, r = !x, mn = (~1) + 1;
  r += mn;
  ans += y & r;
  r = !x; r = (~r) + 1;
  ans += z & r;
  return ans;
}

isLessOrEqual

/*
 * 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 mi = y + ((~x)+1);
  return !(mi & (1<<31));
}

logicalNeg

考虑一个很特殊的情况,如果\(x \ne 0\)\(x\)\(-x\)总有一个符号位为\(0\),即使\(x = Tmin\)
那么只需将\(x\ or\ -x\)即可。

/*
 * logicalNeg - implement the ! operator, using all of
 *              the legal operators except !
 *   Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4
 */
int logicalNeg(int x)
{
  int mx = (~x)+1;
  return ((x | mx)>>31)+1;
}

howManyBits

人类智慧题,我们将整个过程抽象成一个二分的过程,如果用\(k\)位就可以表示,那么\(x\)一定在\(-2^{k-1}\)~\(2^{k-1}-1\)这个范围之内,然后模拟普通二分的过程即可。

/* howManyBits - return the minimum number of bits required to represent x in
 *             two's complement
 *  Examples: howManyBits(12) = 5
 *            howManyBits(298) = 10
 *            howManyBits(-5) = 4
 *            howManyBits(0)  = 1
 *            howManyBits(-1) = 1
 *            howManyBits(0x80000000) = 32
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 90
 *  Rating: 4
 */
int howManyBits(int x)
{
  int flag = 0, ans = 0;
  flag = !(!(x >> 16));
  flag &= !(!((x >> 16) + 1));
  x >>= flag << 4;
  ans += flag << 4;
  flag = !(!(x >> 8));
  flag &= !(!((x >> 8) + 1));
  x >>= flag << 3;
  ans += flag << 3;
  flag = !(!(x >> 4));
  flag &= !(!((x >> 4) + 1));
  x >>= flag << 2;
  ans += flag << 2;
  flag = !(!(x>>2));
  flag &= !(!((x >> 2) + 1));
  x >>= flag << 1;
  ans += flag << 1;
  flag = !(!(x>>1));
  flag &= !(!((x >> 1) + 1));
  x >>= flag;
  ans += flag;
  flag = !(!x); flag &= !(!(x+1));
  ans += flag;
  return ans + 1;
}

The float parts are achieved very ugly, so please not to blame me.

floatScale2

unsigned floatScale2(unsigned uf)
{
  int f = uf & 0x7fffff;
  int e = (uf >> 23) & 0xff;
  int s = uf >> 31;
  if( e == 0xff) return uf;
  if (e){
    e += 1;
    return (s << 31) + (e << 23) + f;
  }
  if ((f & 0x700000) == 1) e = 1; 
  f <<= 1;
  return (s << 31) + (e << 23) + f;
}

floatFloat2Int

int floatFloat2Int(unsigned uf)
{
  int f = uf & 0x7fffff, E;
  int e = (uf >> 23) & 0xff;
  int s = uf >> 31, Bias = (1<<7) - 1;
  int ans = 0;
  if (e == 0xff) return 0x80000000u;
  if(e)E = e - Bias;
  else E = 1 - Bias;
  if( E < 0) return 0;
  else{
    if(E >= 31)return 0x80000000u;
    f += (1<<23);
    if(E > 23)ans = f<<(E-23);
    else ans = f>>(23-E);
  }
  if (s) return (~ans)+1;
  return ans;
}

floatPower2

unsigned floatPower2(int x)
{
  if( x < -150) return 0;
  if( x >= 129) return 0x7f800000;
  if( -126 <= x){
    x += 127;
    return x << 23;
  }
  return 1<<(x+150);
}

Next Lab: [[bomblab]]

posted @ 2023-08-30 14:24  fexuile  阅读(28)  评论(0编辑  收藏  举报