浮点数的存储及表达范围

参考资料:
1. 浮点数进制转换, Mr.Rico个人博客
2. 浮点存储和取值范围,CSDN treasurew 博客
3.【学习记录】正数乘以正数等于负数?| 整数和浮点数在计算机中的存储,B站Up 笨手笨脚oO

一、存储

符号位

指数位

有效数字位

表达这个数字的正负,二进制1表示负,0表示正

存放规范化指数形式的指数位

存放有效数字

32位二进制(4个字节)

符号位

指数位

有效数字位

1bit

8bit

23bit

64位二进制(8字节)

符号位

指数位

有效数字位

1bit

11bit

52bit

别问为什么是这样的!

问就是规定!!!

二、存储举例(以100.1为例)

1. 先变成这个10进制数字的二进制形式

十进制小数转二进制

方法:乘二取整,顺序排列,加上小数点。

案例:

十进制的0.8125转换成二进制:

来源网络

图片来源:参考资料1:浮点数进制转换, Mr.Rico个人博客

十进制的10.8125转换成二进制:  
整数位和小数位分开转换,整数位简单,小数位同上,再用小数点连接。  
10转换成二进制为01010  
所以10.8125转换成二进制为: 01010.1101  

番外:小数二进制转换成十进制

方法: 加权系数展开

来源网络 图片来源:参考资料1:浮点数进制转换, Mr.Rico个人博客

所以本例中的 100.1 转化成二进制为:
整数位:100 —— 二进制:01100100
小数位:0.1 —— 二进制:0.000110011001100…

最终结果:01100100.0001 1001 1001 1001…

2. 把这个二进制转化成标准化指数形式(2为底数)

还是上边的这个数100.1
转化为二进制表达的标准化指数形式:小数点向左移动6位
最终结果约为:1.100100 e-6

PS:  
① 十进制也可以先转换成以2为底数的标准化指数形式,再转换成二进制。     
② 十进制先转化二进制,再转化成标准指数化形式,直接移动位数就行。(为啥是这样的?以我们熟悉的十进制为例: 3.89*10^4,就是小数点向右移动4位,38900)

3. 按照存储结构存储(以32bit为例)

32位二进制(4个字节)

符号位

指数位

有效数字位

1bit

8bit

23bit

① 100.1是正数,所以第一位是0
1.100100 e-6
② 左移6位,表达成e-6,这个指数位存的就是-6;在8位二进制条件下存储。指数是以阶码的形式存储的。

两种方式看他是怎么存储的:

第一种:
① 先求移码:移码是补码的符号位取反,(-6)的补码是:1111 1010 所以移码结果应该是:0111 1010   
④ 再求阶码(浮点数指数位存储形式): 阶码=阶数的移码-1   0111 1001
第二种:
这个指数位存储的二进制用十进制表示恰好是等于:偏置数(8位偏置127;11位偏置1023)+阶数   
127+(-6)= 121  
转换成二进制:0111 1001   
可以看到第二种和第一种方法得出的结果一样  
所以直接用第二种计算简单一点。  

问题又来了???  
偏置值是个什么鬼?  
因为存指数位的那个数据是一个无符号的整数形式的数据,8位无符号的整数形式取值范围为:0~255;但是事实上,指数有负数的情况,例如这道题,指数就是-6.那该如何用一个无符号的整数表达负数呢?   
干脆把0~255劈一半,0~127;-127~-1;那么只要把是负数的数字加上127就变成了一个无符号整数可以表达的形式了。  
所以8位二进制指数偏置值为127;  
64位二进制偏置值为1023  
计算方法:[2^(位数)]/2-1  

③ 有效数字位
1.1001 0000 01100……
由于最高位肯定是1,所以存储时可以把1甩掉,取出来的时候再补上。
所以存到计算机里的是:
1001 0000 0110 0110 0110 011(23位)

最终结果:
【0】【0111 1001】【1001 000 0110 0110 0110 011】

4. 浮点数存取数字范围分析(以32位为例)

根据指数位在内存中存储的数字(e)的大小一共有4种情况 ,其中E表示实际阶数, Bias为偏置值(127或1023);M为小数部分存放的数字

图片来源参考资料3

$1 \le e\le 254$

\(e=0\);\(M\ne0\)

\(e=255\);\(M=0\)

\(e=255\);M$\ne 0$

\(V=(-1)^s*1.M*2^{e-127}\)

\(V=(-1)^S*0.M*2^{-126}\) ,表示正负无穷0,以及接近0的很小的数字

表示无穷

NAN

根据这个规则,我们可以看到,它可以存放0;无穷;那么8位二进制所能表达的一般浮点数的范围是什么呢?

也就是当e取1~254之间的数

4.1 最大一般浮点数:

当e=254时,即二进制为:1111 1110 时;(当e全为1的情况时,即e=255,这时表示的是无穷或者不是一个数字),所以254是指数位表达一般浮点数字时所存放的最大的数字。

减去存放时加上的偏置值127,实际存放的最大阶数为 \(Emax=254-127=127\) ;

有效数字位M可以存放23位,最大即23位全为1时

加上被甩掉的1,所以最终结果以二进制表达为:1.1111……1111(小数点后23个1),再乘以阶数127,这个数字用二进制表达为: $1.1111……1111*2^{127}$

需要注意的是这是二进制的表达方式,阶数是几,就把小数点向右移动几位,所以这个直接把小数点向右移动127位,得到了以二进制表达的最大浮点数:1111111……11111(128个1)

换算成10进制为: $2^{128}-1\approx3.4e38$

这就是32位二进制所能表达的最大浮点数的由来。

4.2 最小一般浮点数

下面分析最小的数,由于这种存储方式,有符号位,所以最小的数肯定是 -(3.4e38);

4.3 绝对值最小的一般浮点数

值得分析的是除去无穷接近于0的情况,所能表示的一般数字种绝对值最小的浮点数(0.000000???)是多少

指数位最小应该是e=1的情况,减去偏置值127,也就是-126;

而有效数字位最小就是全为0,

最终这个绝对值最小的浮点数以二进制表示为: $1.0*2^{-126}$

同理,这个是小数点向左移126位,得到:0.000……000(125个0)1 这是二进制表达的

换算成10进制为: $1*2^{-126}\approx1.2e-38$ (事实上是0.000……000(37个0)11754943……)


本文章使用limfx的vsocde插件快速发布