cmu 15-213 lab 1 datalab

用与非门实现异或

在这里插入图片描述
在这里插入图片描述
与非门在两个输入都是 1 的时候才输出 0 ,异或是两个输入相同为 0,不同为 1。

描述一下就是首先这两个输入进行与非,得到的结果分别和两个输入进行与非,最后两个结果再进行与非。

怎么得出来的???参考 https://cs.stackexchange.com/questions/43342/how-to-construct-xor-gate-using-only-4-nand-gate

A ⊕ B = A B ‾ ( A + B ) = A B ‾ A + A B ‾ B = ( A B ‾ A ) ( A B ‾ B ) ‾ \begin{aligned} A\oplus B&=\overline{AB}(A+B)\\ &=\overline{AB}A+\overline{AB}B\\ &=\overline{(\overline{AB}A)(\overline{AB}B)} \end{aligned} AB=AB(A+B)=ABA+ABB=(ABA)(ABB)

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

求用补码表示的最小 integer

two’s complement integer 就是补码。

这个很简单。

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

判断该补码是否是最大值

用了 8 个 operator ,思路是最大值 0x7fffffff 加一和翻转是相同的(要排除 0xffffffff

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

判断所有奇数位是否为 1

最低位编号为 0

这个也很简单,但是不能直接用 0xaaaaaaaa ,因为只能用 Integer constants 0 through 255 (0xFF), inclusive. 但是没有问题!构造一个就行了,总共用了 7 个 op

/* 
 * 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 m0=0xaa;
  int m1=(m0<<8)|m0;
  int m=(m1<<16)|m1;
  return !((m&x)^m);
}

输出 -x

简单。取反加一

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

判断是否为 ‘0’-‘9’ 的 ASCII

即判断是否在 0x30-0x39 之间

先判断最高的 24 位是不是 0x3!((x>>4)^0x3) ,然后判断最低的 4 位,有两种情况:

  1. 最高位是 0 ,此时表示 0 到 7 :!(x&0x8)
  2. 最高位是 1 ,此时表示 8 到 9: !(x&0x6) (判断 2,3 位同时为 0)

还是很妙的,用了 9 个 op

/* 
 * 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) {
  return !((x>>4)^0x3)&(!(x&0x8)|!(x&0x6));
}

实现 x ? y : z

这里只要判断 x 是否为 0 ,首先取反,然后向左移 31 位,将判断值移到最高位,然后再向右移 31 位,假如判断值为 1 的话,由于默认右移是算术移位,因此左右移位后就全变成了 1。总共用了 7 个 op

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

实现 ≤ \le

首先判断两个数的符号是否相同,假如符号不同且 x 为负数,那么小于等于成立。

再考虑符号相同的情况,此时应当有 y-x>=0y+(~x+1)>=0

分成这两步处理可以防止计算 y+(~x+1) 时发生溢出。用了 15 个 op

/* 
 * 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 sx=!(x>>31); // x < 0 : 0
  int sy=!(y>>31);
  int ds=sx^sy;
  int xn=ds&!sx;
  int le=!ds&!((y+(~x+1))>>31); // y-x >= 0
  return xn|le;
}

实现逻辑非

思路是把每一位或起来,判断最后是否为 1。刚好用了 12 个 op

/* 
 * 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) {
  x=x|(x>>1);
  x=x|(x>>2);
  x=x|(x>>4);
  x=x|(x>>8);
  x=x|(x>>16);
  return x&0x1^0x1;
}

最少用几位补码表示

这题还是很有意思的,参考了别人的写法。首先把负数进行翻转求解(一个正数需要的位数就是找其最高的 1,一个负数需要的位数就是找其最高的 0),然后依次判断最高 16 位是否全为 0 ,否则的话就至少需要十六位,然后将原 x 向右移掉这已经计算过的十六位,直至 8 位、4 位、2 位、1 位 等。详见代码。最后加的 1 是符号位(0,-1 可以认为只有符号位)

用了 36 个 op

/* 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 s,b16,b8,b4,b2,b1,b0;
  s=x>>31;
  x=(s&~x)|(~s&x);
  b16=!!(x>>16)<<4;
  x=x>>b16;
  b8=!!(x>>8)<<3;
  x=x>>b8;
  b4=!!(x>>4)<<2;
  x=x>>b4;
  b2=!!(x>>2)<<1;
  x=x>>b2;
  b1=!!(x>>1);
  x=x>>b1;
  b0=x;
  return b16+b8+b4+b2+b1+b0+1;
}

浮点数乘 2

输入 32 bit ,表示的形式是单精度浮点数,其格式如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
根据条件判断即可,用了 15 个 op:

/* 
 * floatScale2 - 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 floatScale2(unsigned uf) {
  // uf==+-0
	if(uf==0||uf==0x80000000)return uf;
  // NaN
  if(((uf>>23)&0xff)==0xff)return uf;
  // denormalized values
  if(((uf>>23)&0xff)==0)return (uf&(1<<31))|(uf<<1);
  // exp + 1
  return uf+(1<<23);
}

浮点数转 int

/* 
 * floatFloat2Int - Return bit-level equivalent of expression (int) f
 *   for floating point argument f.
 *   Argument is passed as unsigned int, but
 *   it is to be interpreted as the bit-level representation of a
 *   single-precision floating point value.
 *   Anything out of range (including NaN and infinity) should return
 *   0x80000000u.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
int floatFloat2Int(unsigned uf) {
  int s,e,f;
  s=(uf>>31)&0x1;
  e=(uf>>23)&0xff;
  if((uf==0)||(uf==0x80000000))return 0;
  if(e==0)return 0;
  if(e==0xff)return 0x80000000u;
  f=(uf&0x7fffff)|0x800000;
  e-=127; // minus bias
  if(e<0)return 0;
  if(e>30)return 0x80000000u;
  if(e>23)f=f<<(e-23);
  if(e<23)f=f>>(23-e);
  if(s) f=~f+1;
  return f;
}

浮点数 2.0^x

这个很简单啦,注意小于 2 − 126 2^{-126} 2126 时考虑使用 denormalized 方式进行表示。

用了 16 个 op

/* 
 * floatPower2 - Return bit-level equivalent of the expression 2.0^x
 *   (2.0 raised to the power x) for any 32-bit integer x.
 *
 *   The unsigned value that is returned should have the identical bit
 *   representation as the single-precision floating-point number 2.0^x.
 *   If the result is too small to be represented as a denorm, return
 *   0. If too large, return +INF.
 * 
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while 
 *   Max ops: 30 
 *   Rating: 4
 */
unsigned floatPower2(int x) {
  if(x<-149)return 0;
  if(x>=-149&&x<-126)return 1<<(149+x);
  if(x>=-126&&x<=127)return (x+127)<<23;
  return 0xff<<23;
}

来一张测试图~

Correctness Results     Perf Results
Points  Rating  Errors  Points  Ops     Puzzle
1       1       0       2       8       bitXor
1       1       0       2       1       tmin
1       1       0       2       8       isTmax
2       2       0       2       7       allOddBits
2       2       0       2       2       negate
3       3       0       2       9       isAsciiDigit
3       3       0       2       7       conditional
3       3       0       2       15      isLessOrEqual
4       4       0       2       12      logicalNeg
4       4       0       2       36      howManyBits
4       4       0       2       15      floatScale2
4       4       0       2       22      floatFloat2Int
4       4       0       2       16      floatPower2
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值