【CSAPP】Datalab 详解

Lab要求:

理解内在于系统的存储逻辑与方式,并利用其特性完成函数。

实验机器:

VMware的虚拟机——Ubuntu-20.04

实验材料:

CSAPP的官网selfstudy-handout:
点击以进入CMU提供的下载渠道
一定记得看Writeup!
在这里插入图片描述

第一题

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

允许使用的二元运算符只有&,
观察x & y的结果发现(此处只观察每一个单一bit):
x & y = 1 (11)
x & y = 0(01,10,00)

ck1= x & y,只要对ck1取反,再排除00就可以了,
想到:
x & y = 1 (11)
则有:
~x & ~y = 1 (00)
再记,ck2=~x & ~y

所以答案有两个要求,一是 x & y == 0,二是 ~x & ~y != 1
即 ans= ~ck1 & ~ck2;

int bitXor(int x, int y) {
  	return (~(~x & ~y))&(~(x&y));
}

第二题

/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */

Tmin就是符号位为1,其他所有位为0。
那么 就是:

int tmin(void) {
  return 1<<31;
}

第三题

/*
 * isTmax - returns 1 if x is the maximum, two's complement number,
 *     and 0 otherwise 
 *   Legal ops: ! ~ & ^ | +
 *   Max ops: 10
 *   Rating: 1
 */

Tmax有一个挺独特的点: Tmax + 1 == ~Tmax;
不过 -1 也会满足这一等式,但只有这两个数会满足此等式,这就是一个不错的出发点。
总体思路:

  1. 不妨先检查 x+1 是否等于 ~x
  2. 再保证x不等于-1

ck1 = !( (x+1) ^ (~x) )
a ^ b 当且仅当 a == b 时,为 0;
再做一次逻辑取反,以确保 x+1 == ~x

下一步就是确保 x != -1
x+1 != 0
ck2 = !!(x+1)

所以ans = ck1 & ck2

当时写得有点没条理,但意思是一样的。

int isTmax(int x) {
  int ck1=~x;
  int ck2=x+1;

  int ret=!(ck1^ck2);
  // Then check if x==-1 0r x+1==0
  return !!ck2 & ret;
}

第四题

/* 
 * 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
 */

记得: 1010101 0 b i n a r y = 17 0 d e c = 0 x A A 10101010_{binary}=170_{dec}=0xAA 10101010binary=170dec=0xAA

主要思路:

  1. 可以用0xAAAAAAAA与x做 按位& 来获取它的所有偶数位,记 cpt = 0xAAAAAAAA & x
  2. 在对比ck1 与 0xAAAAAAAA是否相等。
int allOddBits(int x) {
  int t= 170 + (170<<8) + (170<<16) + (170<<24);
  return !((t & x)^(t));
}

第五题

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

用原书中的加法逆元来解释这个所谓的“-x”,在int中不是每一个数加个负号就可以变成自己的加法逆元的,比如Tmin就会溢出,但好消息是,每个数都能用方程: x + x a d v e r s e = 0 x+x_{adverse}=0 x+xadverse=0 来解出一个加法逆元。

我们发现:~x + x = 0xFFFFFFFF,即 -1
~x+x+1 = -1+1 =0
所以x的加法逆元为~x+1

int negate(int x) {
  return (~x)+1;
}

第六题

/* 
 * 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(x+(1<<31)+1) & (x+(1<<31)+1)
 *   Rating: 3
 */

其实就是让我们判断一个数是否在 [0x30,0x39] 中。
在位运算中,判断一个数小于零是最简单的操作,所以需要对数字作出一点等价变换:
x ≥ 0 x 30 等价于 ! ( x − 0 x 30 < 0 ) x\ge 0x30 \quad \textbf{等价于}\quad !(x-0x30< 0) x0x30等价于!(x0x30<0)

同样地,也有:
x ≤ 0 x 39 等价于 ! ( 0 x 39 − x < 0 ) x\le 0x39 \quad \textbf{等价于}\quad !(0x39-x< 0) x0x39等价于!(0x39x<0)

int isAsciiDigit(int x) {
 int left= !((x+~(0x30)+1)>>31);
 int right=!((0x39+(~x)+1)>>31);

 return left & right;
}

第七题

/* 
 * conditional - same as x ? y : z 
 *   Example: conditional(2,4,5) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3
 */

初次做这道题会有点无从下手,但掌握以下思想会变简单不少:
return (entry1 & y) | (entry2 & z):
就是在想输出y的时候,entry1 = 0xFFFFFFFF,entry2 = 0x0,一二对调则是输出z。
其中当 x != 0 时,entry1=0xFFFFFFFF,而 entry2=0x0;
x == 0 时,entry1=0x0,而 entry2=0xFFFFFFFF;
那么:
e n t r y 1 = ( ( ! ! x ) < < 31 ) > > 31 entry_{1}=((!!x)<<31)>>31 entry1=((!!x)<<31)>>31
那entry2就等于 ~entry1

int conditional(int x, int y, int z) {
  int bm_y= ((!!x)<<31)>>31;
  int bm_z= ~bm_y;

  return (bm_y & y) | (bm_z & z);
}

第八题

/* 
 * isLessOrEqual - if x <= y  then return 1, else return 0 
 *   Example: isLessOrEqual(4,5) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */

这题挺恶心的,看上去挺容易但会很容易错。
以下,把int分为两类:自然数,和负数。
主要思路:

  1. 符号比较,数的类型不同一定有天然的大小关系
  2. 比较同号的数:
    a. 同为自然数可以正常比较,因为对正数取负是没有溢出风险的
    b. 同为负数,如果有Tmin,则会有天然的大小关系。
    如果没有Tmin则可以正常比较。

同样地,我们对于条件分类使用之前在conditional中使用过的通道的方法。

先设置一下辅助参数如下:

int sx=x>>31;
int sy=y>>31;
int Tmin=1<<31;
int ANS;

x ≤ y x \le y xy 可能会有的几种情况:
Case1 x < 0 且 y ≥ 0 x < 0\quad 且\quad y\ge0 x<0y0
这种情况直接返回1

int entry1= sx & !sy;
ANS = entry1 & 1;

Case2 x ≥ 0 且 y ≥ 0 x \ge 0\quad 且\quad y\ge0 x0y0
直接安全取负,判断是否小于0就可以了

int entry2= !sx & !sy;
ANS |= entry2 & !((y+~x+1)>>31);

Case3 x < 0 且 y < 0 x < 0\quad 且\quad y<0 x<0y<0
因为要对x取反,那么需要知道x是否为Tmin。
若x==Tmin,则直接return 1;
若不为Tmin,那直接判断就好。

int entry3= sx & sy;
ANS |= entry3 & (!(x^Tmin) | !((y+~x+1)>>31));

最终为:

int isLessOrEqual(int x, int y) {
	int sx=x>>31;
	int sy=y>>31;
	int Tmin=1<<31;
	int ANS=0;
	int cp_xy=!((y+~x+1)>>31);
	
	int entry1= sx & !sy;
	ANS |= entry1 & 1;
	
	int entry2= !sx & !sy;
	ANS |= entry2 & cp_xy;
	
	int entry3= sx & sy;
	ANS |= entry3 & (!(x^Tmin) | cp_xy);
	
	return ANS;
}

第九题

/* 
 * 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 
 */

只有当x==0时,才会输出1;
解这道题,需要利用0的独特性质:
N u m ⋅ N u m a d v e r s e ≥ 0 Num \cdot Num_{adverse}\ge0 NumNumadverse0
即Num与它的加法逆元同号。
但是需要注意的是,满足上述的等式的 Num 有两个,Tmin0

主要思路:

  1. 确定x与它的加法逆元同号
  2. 排除Tmin的情况
int logicalNeg(int x) {
  int s1=(~((x ^ (~x+1)) >>31)) & 1;
  int s2=(~(x>>31)) & 1;

  return s1 & s2;
}

检测是否同号的方式有一点比较巧妙,先使x与~x+1做异或,仅看第31位,若为1则异号,若为0则同号,再左移31位使第31位到达第0位,后面就不说了。


第十题

/* 
 *  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
 */

这道题真是二分查找思想的极致运用了。
首先,要先理解数据,比如,0x11111事实上只用一位就可以表示。
做一个小小的示例:
000 1   111 0   0000   0000   |   0000   0000   0000   000 0 b i n a r y 000\textbf1\ \textbf{111}0\ 0000\ 0000\ \textbf|\ 0000\ 0000\ 0000\ 0000_{binary} 0001 1110 0000 0000 | 0000 0000 0000 0000binary

111 0   000 1   1111   1111   |   1111   1111   1111   111 1 b i n a r y 111\textbf0\ \textbf{000}1\ 1111\ 1111 \ \textbf|\ 1111\ 1111\ 1111\ 1111_{binary} 1110 0001 1111 1111 | 1111 1111 1111 1111binary
会得到一样的答案,但前者会明显更好处理。
那不妨将所有的负数都做一次取反,而正数则保持不变。

int s=x>>31;
x= s^x;

这做法有点奇妙,如果x为负数,则s = 0 x F F F F F F F F 0xFFFFFFFF 0xFFFFFFFF,s^x就等价于~x
如果x为正数,则s= 0 x 00000000 0x00000000 0x00000000,此时s^x等价于啥也不干。

做完这个处理之后,就是本题的精华所在了。
先将x分为上下16位,若上16位已被使用,则将其左移16位,若没有,则啥也不干。
以这种处理方式会发现,问题被缩小了,从求解32位数需要的实际位数,变成了求解16位数需要的实际位数再加上16或是0(看情况)。以这种方式一次向下查找。

需要注意,我们找的位置是最大权重的bit所在位,所以最后的答案应该加二,但是0,-1的情况就被忽略了,因此要分一次类,然后依然用通道法完成。

int howManyBits(int x) {
 int s=x>>31;
 x= s^x;
 
 int bit_16=!!(x>>16);
 x=x>>(bit_16<<4);
 
 int bit_8=!!(x>>8);
 x=x>>(bit_8<<3);
 
 int bit_4=!!(x>>4);
 x=x>>(bit_4<<2);
 
 int bit_2=!!(x>>2);
 x=x>>(bit_2<<1);
 
 int bit_1=!!(x>>1);
 x=x>>(bit_1<<0);
 
 int ck=(!x) | (!(~x));
 ck=(ck<<31)>>31;
 
 int sd_ans=(bit_16<<4)+(bit_8<<3)+(bit_4<<2)+(bit_2<<1)+(bit_1)+2;
 
 return (ck & 1) | ((~ck) & sd_ans);
}

Float Part

背景知识:
u f = 0 x 0 100    0000    1 101    0000   ∣   0000    0000    0000    0000 23      \begin{matrix} uf=0x {\color{Red} 0} {\color{Green}100\ \ 0000\ \ 1 } {\color{Violet} 101\ \ 0000\ |\ 0000\ \ 0000\ \ 0000\ \ 0000} \\ _{_{{\color{Green}23}}}\qquad\qquad\qquad\;\; \end{matrix} uf=0x0100  0000  1101  0000  0000  0000  0000  000023
其中红色为sign bits,
绿色为exp bits,
紫色为frac bits。

其实对于计算机来说,数据都只是对字段的某种理解方式,如果uf为int,那么a就是 108842188 8 d e c 1088421888_{dec} 1088421888dec,但 uf 若为float,那么 uf 就是 6.5 6.5 6.5。(详见CSAPP Chapter 2)

对于浮点数的处理,分为三种情况:
1,Normal: e x p ≠ 0 exp\ne0 exp=0 && e x p ≠ 255 exp\ne255 exp=255
2,Denormal: e x p = 0 exp=0 exp=0
1,NaN: e x p = 255 exp=255 exp=255


第十一题

/* 
 * 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 int s=(uf>>31);
  unsigned int exp=(uf<<1)>>24;
  unsigned int frac=(uf<<9)>>9;

先把数据按照字段切割如上。

// exp==255
if(!(exp^255)) return ans1;
// exp==0 && frac==0
else if(!frac && !exp) return ans2;
// exp==0 && frac!=0
else if(!exp) return ans3;
// exp!=0 && exp!=255
return ans4;

对于代码中的第一个情况,即 e x p = 255 exp=255 exp=255,按照要求NaN原样返回,而 2 ⋅ i n f i n i t e 2\cdot infinite 2infinite 仍然是 i n f i n i t e infinite infinite,所以: a n s 1 = u f ; ans1=uf; ans1=uf;

对于代码中的第二个情况,即 e x p = 0 exp=0 exp=0 && f r a c = 0 frac=0 frac=0,因为 0 × 2 = 0 0\times2=0 0×2=0,所以: a n s 2 = u f ; ans2=uf; ans2=uf;

对于代码中的第三个情况,即 e x p = 0 exp=0 exp=0 && f r a c ≠ 0 frac\ne0 frac=0
a = ( − 1 ) s ⋅ 2 e x p − b i a s ⋅ ( 0 . f 22 f 21 … f 0 ) a=(-1)^{s}\cdot 2^{exp-bias}\cdot(0\textbf.f_{22}f_{21}…f_{0}) a=(1)s2expbias(0.f22f21f0)
所以乘以二后的结果可以表示为:
2 ⋅ a = ( − 1 ) s ⋅ 2 e x p − b i a s ⋅ ( f 22 . f 21 … f 0 0 ) 2\cdot a=(-1)^{s}\cdot 2^{exp-bias}\cdot (f_{22}\textbf.f_{21}…f_{0}0) 2a=(1)s2expbias(f22.f21f00)
因此,就算frac<<1导致了越界,会发现这正好就是我们想要的结果,因为情况由Normal变为了Denormal,但这两种情况计算exp的不同,却恰恰导致了最终结果的相同。
a n s 3 = ( s < < 31 ) + ( f r a c < < 1 ) ; ans3=(s<<31) + (frac<<1); ans3=(s<<31)+(frac<<1);
对于代码中的第四个情况,即 e x p ≠ 0 exp\ne0 exp=0 && e x p ≠ 255 exp\ne255 exp=255
这种情况就是最直接的理解, e x p = e x p + 1 exp=exp+1 exp=exp+1 即可。
a n s 4 = ( s < < 31 ) + [ ( e x p + 1 ) < < 23 ] + f r a c ; ans4=(s<<31) + [(exp+1)<<23] + frac; ans4=(s<<31)+[(exp+1)<<23]+frac;

最终程序为:

unsigned floatScale2(unsigned uf) {
  unsigned int s=(uf>>31);
  unsigned int exp=(uf<<1)>>24;
  unsigned int frac=(uf<<9)>>9;
  // exp == 255
  if(!(exp^255)) return uf;
  
  // exp == 0   && frac == 0
  else if(!frac && !exp) return uf;

  // exp == 0   && frac != 0
  else if(!exp) return (s<<31)+(frac<<1);

  // 0<exp<255
  else return (s<<31)+((exp+1)<<23)+frac;
}

第十二题

/* 
 * 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) {
  unsigned int s=(uf>>31);
  unsigned int exp=(uf<<1)>>24;
  unsigned int frac=(uf<<9)>>9;
  ……
}

还是分类讨论:
1,Normal: e x p ≠ 0 exp\ne0 exp=0 && e x p ≠ 255 exp\ne255 exp=255
2,Denormal: e x p = 0 exp=0 exp=0
1,NaN or Infinite: e x p = 255 exp=255 exp=255

  ……
  //exp==255 (NaN or Infinite)
  if(!(exp^255)) return ans1

  //exp==0
  else if(!exp) return ans2;
  
  //0<exp<255 (normal case)
  else ans3;
}

Case 1 e x p = 255 exp=255 exp=255
按照题意,直接返回0x80000000u。
Case 2 e x p = 0 exp=0 exp=0
因为exp若为0至多 ( 1 2 ) 126 (\frac{1}{2})^{126} (21)126,直接返回0x0。
Case 3 0 < e x p < 255 0<exp<255 0<exp<255
此时可以把 uf变为 ( 1 . f 22 f 21 f 20 … f 0 ) < < ( e x p − b i a s ) (1\textbf.f_{22}f_{21}f_{20}…f_{0})<<(exp-bias) (1.f22f21f20f0)<<(expbias)

比如 e x p − b i a s = 2 exp-bias=2 expbias=2:
此时, u f = 1 f 22 f 21 . f 20 … f 0 0 0 b i n a r y uf=1f_{22}f_{21}\textbf.f_{20}…f_{0}00_{_{binary}} uf=1f22f21.f20f000binary
而转化为int后直接无视小数点后的数字,即 u f = 1 f 22 f 21 uf=1f_{22}f_{21} uf=1f22f21

  • 但同样要注意细节,若 u f = 1 f 22 f 21 f 20 … f 0 0000000 0 b i n a r y uf=1f_{22}f_{21}f_{20}…f_{0}{\color{Green}0000000}{\color{Red}0}_{_{binary}} uf=1f22f21f20f000000000binary
    那么红色的0会使最终答案越界,因此需要返回0x80000000u。
  • 还有 f r a c = 1 f 22 f 21 f 20 … f 0 frac=1f_{22}f_{21}f_{20}…f_{0} frac=1f22f21f20f0 注意左移或者右移的方向,因为系会将 f r a c > > ( − 2 ) frac>>(-2) frac>>(2)理解为 f r a c > > 30 frac>>30 frac>>30,而这与我们的本意相悖。
int floatFloat2Int(unsigned uf) {
  unsigned int s=(uf>>31);
  unsigned int exp=(uf<<1)>>24;
  unsigned int frac=(uf<<9)>>9;
  // NaN || infinity
  if(!(exp^255)) return 0x80000000u;
  // denormal case(exp == 0)
  else if(!exp) return 0;
  // normal case(0<exp<255)
  else{
    frac+=(1<<23);
    int bits=(150u-exp);

    // bits<-7(这种情况会使只有0-23位的frac发生溢出)
    if((bits+7)>>31) return 0x80000000u;
    else{
      int tmp;
      // bits小于0
      if(bits>>31) tmp=frac<<((~bits)+1);
      // bits大于31
      else if((32+(~bits))>>31) tmp=0;
      else tmp=frac>>bits;

      return (!s)?tmp:(~tmp)+1;
    }
  }
}

第十三题

/* 
 * 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
 */

a = 0 x 0 000    0000    0 000    0000   ∣   0000    0000    0000    0001 23      \begin{matrix} a=0x {\color{Red} 0} {\color{Green}000\ \ 0000\ \ 0 } {\color{Violet} 000\ \ 0000\ |\ 0000\ \ 0000\ \ 0000\ \ 0001} \\ _{_{{\color{Green}23}}}\qquad\qquad\qquad\;\; \end{matrix} a=0x0000  0000  0000  0000  0000  0000  0000  000123
Case1:当 x < − ( 126 + 23 ) x<-(126+23) x<(126+23)
2 x < 0 x 0 000    0000    0 000    0000   ∣   0000    0000    0000    0001 2^{x}<0x {\color{Red} 0} {\color{Green}000\ \ 0000\ \ 0 } {\color{Violet} 000\ \ 0000\ |\ 0000\ \ 0000\ \ 0000\ \ 0001} 2x<0x0000  0000  0000  0000  0000  0000  0000  0001,即float能表示的最小数。
此时视为过小,按要求需要返回0
∴ a n s 1 = 0 \therefore ans1=0 ans1=0

Case2:当 − ( 126 + 23 ) ≤ x ≤ − 127 -(126+23)\le x \le-127 (126+23)x127
做一下分解:
2 x = 2 − 126 + ( − b i t s ) = 2 E × M   \begin{matrix} 2^{x}=2^{-126+(-bits)} \\ =2^{E}\times M \, \end{matrix} 2x=2126+(bits)=2E×M
所以 b i t s = − 126 − x bits=-126-x bits=126x

∴ a n s 2 = ( 1 < < 23 ) > > b i t s \therefore ans2=(1<<23)>>bits ans2=(1<<23)>>bits
Case3:当 − 126 ≤ x ≤ ( 254 − 127 ) -126\le x \le(254-127) 126x(254127)
此时
2 x = 2 e x p − 127 2^{x}=2^{exp-127} 2x=2exp127
∴ e x p = x + 127 \therefore exp=x +127 exp=x+127
∴ a n s 3 = ( e x p < < 23 ) \therefore ans3=(exp<<23) ans3=(exp<<23)

Case4:当 x > ( 254 − 127 ) x>(254-127) x>(254127)
∴    2 x > 0 x 0 111    1111    0 000    0000   ∣   0000    0000    0000    0000 \therefore \;2^{x}>0x {\color{Red} 0} {\color{Green}111\ \ 1111\ \ 0 } {\color{Violet} 000\ \ 0000\ |\ 0000\ \ 0000\ \ 0000\ \ 0000} 2x>0x0111  1111  0000  0000  0000  0000  0000  0000
按照题意视为过大,返回 inf,即 0 x 0 111    1111    1 000    0000   ∣   0000    0000    0000    0000 0x {\color{Red} 0} {\color{Green}111\ \ 1111\ \ 1 } {\color{Violet} 000\ \ 0000\ |\ 0000\ \ 0000\ \ 0000\ \ 0000} 0x0111  1111  1000  0000  0000  0000  0000  0000

∴ a n s 4 = ( 255 < < 23 ) \therefore ans4=(255<<23) ans4=(255<<23)

unsigned floatPower2(int x) {
  unsigned int exp=0;

  if(x+149>>31) return exp;
  else if((128 + ~x)>>31){
    exp=255;
    return exp<<23;
  }
  else if(x+126>>31){
    unsigned int frac=1<<23;
    int bits=~(x+126)+1;
    return frac>>bits;
  }
  else{
    exp=x+127;
    return exp<<23;
  }
}
  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值