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 也会满足这一等式,但只有这两个数会满足此等式,这就是一个不错的出发点。
总体思路:
- 不妨先检查 x+1 是否等于 ~x
- 再保证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
主要思路:
- 可以用0xAAAAAAAA与x做 按位& 来获取它的所有偶数位,记 cpt = 0xAAAAAAAA & x
- 在对比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)
x≥0x30等价于!(x−0x30<0)
同样地,也有:
x
≤
0
x
39
等价于
!
(
0
x
39
−
x
<
0
)
x\le 0x39 \quad \textbf{等价于}\quad !(0x39-x< 0)
x≤0x39等价于!(0x39−x<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分为两类:自然数,和负数。
主要思路:
- 符号比较,数的类型不同一定有天然的大小关系
- 比较同号的数:
a. 同为自然数可以正常比较,因为对正数取负是没有溢出风险的
b. 同为负数,如果有Tmin,则会有天然的大小关系。
如果没有Tmin则可以正常比较。
同样地,我们对于条件分类使用之前在conditional中使用过的通道的方法。
先设置一下辅助参数如下:
int sx=x>>31;
int sy=y>>31;
int Tmin=1<<31;
int ANS;
x
≤
y
x \le y
x≤y 可能会有的几种情况:
Case1:
x
<
0
且
y
≥
0
x < 0\quad 且\quad y\ge0
x<0且y≥0
这种情况直接返回1
int entry1= sx & !sy;
ANS = entry1 & 1;
Case2:
x
≥
0
且
y
≥
0
x \ge 0\quad 且\quad y\ge0
x≥0且y≥0
直接安全取负,判断是否小于0就可以了
int entry2= !sx & !sy;
ANS |= entry2 & !((y+~x+1)>>31);
Case3:
x
<
0
且
y
<
0
x < 0\quad 且\quad y<0
x<0且y<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
Num⋅Numadverse≥0
即Num与它的加法逆元同号。
但是需要注意的是,满足上述的等式的 Num 有两个,Tmin 与 0;
主要思路:
- 确定x与它的加法逆元同号
- 排除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 2⋅infinite 仍然是 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)s⋅2exp−bias⋅(0.f22f21…f0)
所以乘以二后的结果可以表示为:
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)
2⋅a=(−1)s⋅2exp−bias⋅(f22.f21…f00)
因此,就算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.f22f21f20…f0)<<(exp−bias)
比如
e
x
p
−
b
i
a
s
=
2
exp-bias=2
exp−bias=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.f20…f000binary
而转化为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=1f22f21f20…f000000000binary,
那么红色的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=1f22f21f20…f0 注意左移或者右移的方向,因为系会将 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)≤x≤−127,
做一下分解:
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=2−126+(−bits)=2E×M
所以
b
i
t
s
=
−
126
−
x
bits=-126-x
bits=−126−x
∴
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)
−126≤x≤(254−127),
此时
2
x
=
2
e
x
p
−
127
2^{x}=2^{exp-127}
2x=2exp−127
∴
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>(254−127),
∴
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;
}
}