1. 这篇博客将要讨论什么?
说来惭愧,做为计算机科班出身的人,计算机基础知识掌握并不扎实,这里的基础指的是计算机体系结构中的内容,诸如数据的表示和处理,如float的表示和运算等。看《CSAPP》方知人家老外把这个东西当成重中之重,大量详细的原理介绍,并配套大量例题。当初本科学的时候,很简单的了解了下概念而已,因此应该直接将《CSAPP》当作教材来用,里面习题全作,这样CS出来的基本知识将掌握的很扎实。html
学艺不精的后果就在于:学而不思则罔。圣人太厉害了,总结得很到位。好比最近项目中涉及到浮点和定点的转换,本身就有点蒙,边看边实验,还算理解了,做文以记之。web
一直以来,程序中接触的数据类型都是int整型,char字符型,float单精度浮点型,double双精度浮点型。看到浮点和定点一直不知道如何划分这个概念的范畴。觉得浮点就是float表示小数,定点就是int可表示整数而已。通过学习明白了显然是错误的。应该是这样划分的:网络
浮点:小数点非固定的数,可表示数据范围较广,整数,小数均可表示。包含float,double;
定点:小数点固定,可表示整数,小数。int本质是小数点位于末尾的32位定点数而已;
有了这个认识,后面的讨论就能够开始了。app
2. 浮点数的表示法
浮点数以float为例讨论。svg
2.1 IEEE 754标准
规定浮点数格式为:V
=
(
−
1
)
s
×
M
×
2
E
V = (-1)^s×M×2^EV=(−1)s×M×2E学习
s表示符号位,当s=0,V为正数;当s=1,V为负数
M表示尾数,2
>
M
>
=
1
2>M>=12>M>=1
E表示阶码
将其封装到32位的字中:字体
符号位
阶码
尾数
1
8
23
根据32位数计算为十进制:V
=
(
−
1
)
s
×
(
1.
M
)
×
2
(
E
−
127
)
V = (-1)^s×(1.M)×2^{(E-127)}V=(−1)s×(1.M)×2(E−127)spa
能够得出如下结论:orm
浮点数表示比整型那些更为复杂。如int中0…01000表示8,0…01001表示9,而浮点不能这样简单。
浮点数不能移位。由于各个位有特殊含义。像int数乘2能够左移1位实现。
2.2 浮点数的“浮”字体如今哪里?
咱们说浮点数的小数点不是固定的,是浮动的,那么如何理解?经过例子可直观体验。xml
符号
阶码
尾数
0
0111
001
这个浮点数表示十进制的1.125
符号
阶码
尾数
0
0111
010
若阶码不变,尾数加1,则表示十进制的1.25
符号
阶码
尾数
0
1000
001
若尾数不变,阶码加1,则表示十进制的2.25
3. 定点数的表示法
对于计算机来讲,浮点定点的概念是看不见的,由于它只能看到:0…00001110,至于它表示多少,是逻辑层面的设置。你若是让它是int那就按照int表示法对每一个位赋予意义,若是你让它是float就按照float表示法赋予意义。
对于00011100
0001110000011100表示的定点数:
若是咱们设定小数点是位于最后一位的,即00011100.
00011100.00011100.则其表示28
若设定小数点位于后三位的,即00011.100
00011.10000011.100则其表示3.50
若设定小数点位于后四位的,即0001.1100
0001.11000001.1100则其表示1.75
能够看到:
小数位数越多,表示的精度越高。若小数点后有n位,则其表示的最大精度为1
/
(
2
n
)
1/(2^n)1/(2n);
整数位数越多,可表示的最大值越大。
以8位为例,最高位为符号位:
若整数位占4位,小数位占3位,则其最大精度为0.125,最大值为15.875
若整数位占5位,小数位占2位,则其最大精度为0.250,最大值为31.750
若整数位占6位,小数位占1位,则其最大精度为0.500,最大值为63.500
若整数位占7位,小数位占0位,则其最大精度为1.000,最大值为127
4. 浮点数 & 定点数
4.1 为什么要把浮点数转换为定点数呢?
这来源于项目中神经网络的需求,网络中大量的参数,若是所有用F32表示,一是占用空间大,二是读取效率不高。
若是咱们能够将某些浮点数转换为定点数表示,在接受精度损失的前提下,每次就能够读取多个进行运行,可显著提升运算效率。
举例来讲,咱们用8位定点数,1个符号位,4个整数位,3个小数位,则其可表示范围是-16.00~15.875,最大精度0.125。
有几个浮点数:0.145,1.231,2.364,7.512,每一个须要32bit表示。
若是咱们将每一个量化成一个8位定点数,好比经过某种方法获得:1,10,19,60
此时每一个数须要8bit表示。那么读一个浮点数,能够同时读4个定点数,且计算效率能够提升。固然这样作是有风险的:
损失精度,好比再将上述定点数转化为浮点数:0.125,1.250, 2.375,7.500;
定点数表示范围有限,加法有可能会溢出,须要拿int16或int32来暂存中间结果;
4.2 如何将浮点数转换为定点数?
咱们用8位定点数,1个符号位,4个整数位,3个小数位。这个3称为量化系数。该过程称为量化。
(咱们老是将非离散值量化到离散值空间,处理更为简单)
i
n
t
8
=
f
l
o
a
t
32  
∗  
2
(
3
)
int8 = float32 \,\,* \,\, 2^{(3)}int8=float32∗2(3)
如:i
n
t
8
(
10
)
=
f
l
o
a
t
32
(
1.231
)  
∗  
2
(
3
)
int8(10) = float32(1.231) \,\,* \,\, 2^{(3)}int8(10)=float32(1.231)∗2(3)
4.3 如何将定点数转换为浮点数?
该过程称为反量化。
f
l
o
a
t
32
=
i
n
t
8  
/  
2
(
3
)
float32 = int8 \,\,/ \,\, 2^{(3)}float32=int8/2(3)
如:f
l
o
a
t
32
(
1.250
)
=
i
n
t
8
(
10
)  
/  
2
(
3
)
float32(1.250) = int8(10) \,\,/ \,\, 2^{(3)}float32(1.250)=int8(10)/2(3)
4.4 note
能够这样理解:量化系数 n
nn 决定了咱们逻辑上认为01序列中可表示的单位值 1
/
(
2
n
)
1/{(2^n)}1/(2n),CPU读取的数字表示有多少份单位值。
举例来讲,对于固定的01序列值:0001,1100
量化系数
CPU读取值
单位值
表示逻辑值
3
28
0.125
3.5
2
28
0.250
7.0
一样的int8数,由于量化系数的不一样,表明着不一样的f32值。
还有个note:
定点数加减时须要量化系数相同,其值有可能溢出,须要更大定点数来暂存中间值;
两个定点数乘法后若是须要转化为f32,则反量化系数变为2
∗
n
2*n2∗n
5. 总结
能够看到:
浮点数和定点数的转换是一种映射。将较为密集的数据空间(F32)映射到较为稀疏的空间(int8);
定点数的小数点实际中是没有的,这只是咱们逻辑上的一种设定。01序列是同样的,CPU读取都是相同的,由于咱们逻辑上小数点的不一样位置,咱们认为它表明的值是不一样的;
如果觉得《c语言定点数和浮点数的转换 浮点数和定点数的相互转换(浮点数量化为定点)...》对你有帮助,请点赞、收藏,并留下你的观点哦!