一、浮点数精度损失问题
0.1+0.2不等于0.3,这个问题大家在高级语言编程中经常遇到,为什么呢?
0.2转换为浮点数:
0.2 转换为二进制数的过程为,不断乘以 2,直到不存在小数为止,但0.2在转换过程中会出现无限循环
0.2 * 2 = 0.4 -> 0
0.4 * 2 = 0.8 -> 0
0.8 * 2 = 1.6 -> 1
0.6 * 2 = 1.2 -> 1
0.2 * 2 = 0.4 -> 0(发生循环)
...
得到的整数部分从上到下排列,结果: 0.2(十) = 0.00110…(二) 无限
因为0.2 无法精确转换成二进制小数,而计算机在表示一个数字时,宽度是有限的(单精度32、双精度64),无限循环的小数存储在计算机时,只能被截断,所以就会导致小数精度发生损失的情况。
二、浮点数表示的数值范围
1、以10.25为例,转换为二进制
整数部分:10的二进制表示为1010。
小数部分:0.25的二进制表示需要通过乘2取整法来计算。
0.25乘以2得到0.5,取整得到0;
再将0.5乘以2得到1.0,取整得到1;
因此,0.25的二进制表示为0.01。
整合:10.25的二进制表示为1010.01。
科学计数法的形式:1.01001 × 2^3。
阶码:2^3 ,阶基-2,阶值-3
尾数:1.01001忽略小数点前面的1,尾数为01001
2、浮点32位表示范围-非负阶、规格化
根据IEEE 754标准,二进制浮点数的32位表示包括1位符号位、8位指数位和23位尾数位
(1)、阶码范围
8位:1个阶符,7个阶值 采用非负阶–只有正数和0
最小:0 0000000 值为 0
最大:0 11111111 值为 2^7 - 1
阶码范围:0 ~ (2^7 - 1 )
(2)、尾数范围
23位
最小:. 0000 0000 0000 0000 0000 000
但“ 规格化”,尾数部分的最高位应为1
最小: .1000 0000 0000 0000 0000 000
注意是小数点后面的23位,转十进制(2^-1 代表2的-1次幂):
1 * 2^-1 +0 * 2 ^-2 +…0 * 2 ^-23= 2 ^-1 = 1/2
最大: 1111 1111 1111 1111 1111 111
转为十进制:
1 * 2 ^-1 +1 * 2 ^-2 + …1 * 2 ^-23 如何计算?
可以想象成:
0.1111 1111 1111 1111 1111 111 +0.0000 0000 0000 0000 0000 001=1
0.1111 1111 1111 1111 1111 111=1 - 0.0000 0000 0000 0000 0000 001
=1 - (2^ -23)
(3)、32位浮点数范围
公式:F=M∗2 ^E
最小浮点数:阶最小 0 ,尾最小1/2
(1/2) * 2 ^0=1/2
最大浮点数:阶最大 2^7 - 1 ,尾最大 1- 2 ^-23
(1- 2 ^-23)* 2 ^ ( 2 ^7-1 )
3、浮点32位表示范围-全体
(1)参考如下表:
(2)解决问题
【1】例1:前面提出的问题:
注意: 阶码用移码表示,尾数用补码表示
带入公式计算:F = (-1)^S * M * R^E**
阶数-去最大值,因为负数乘以最大阶码为最小的负数,正数乘以最大阶码为最大的正数,所以阶数就取63
该浮点数最大正数:(1-2^-8)x2 ^63
该浮点数最小负数: -1 x 2 ^63
答案:B
【2】例2
阶码:1 0001 第一位是阶符,1表示负数
0001是补码,转换为原码,补码转原码“取反加1”,与原码转补码方式一样
0001–取反–>1110–加1–>1111 十进制为15
因为是负数,所以为-15
阶基:2
最后为 2 ^ -15
尾数:数符0,表示正数
尾数10位:.0000000001 小数点后面的10位
0 * 2 ^ -1 + … 1 * 2^ -10= 2 ^ -10
结果:2 ^ -15 x 2 ^ -10,选B