IEEE754 单精度浮点数表示方式、与大数吃小数原理

1.IEEE单精度浮点数

1.1 表示方式

        作为一个“正经”的CPU,运算使用的单精度浮点数也就是C语言中的float类型数据,在存储器、寄存器等位置存储形式都是这样的:

                                                图 IEEE 单精度浮点表示方式

        1 bit 符号位:很明显,表示正负的

        8 bit 指数位:   以2为底的指数

        23 位尾数位:理解成有效数字位(2进制)

1.2 手算浮点数

        代表的浮点值的计算方式如下表:

        

   图 单精度浮点数值计算

        如果觉得看的费劲儿,举个例子:

        例子1:寄存器\内存里的32位内容是 0b1_10000000_10000000000000000000000,这代表的浮点数是多少?

       :8位指数位,不全为0,也不全为1,所以这是规范化数,符号位为1,则判断是规范化负数,则计算公式为 -2^{(128 - 127)}*(2^{0}+2^{-1}) = -2*1.5 = -3,计算结果为-3。

        

        例子2:寄存器\内存里的32位内容是 0b1_11111111_10000000000000000000000,这代表的浮点数是多少?

       :8位指数位全为1,则浮点数为正负无穷大、NaN(Not a Number)中之一,因为尾数位不等于0,所以这代表的浮点数为NaN。

        例子3:寄存器\内存里的32位内容是 0b1_11111111_00000000000000000000000,这代表的浮点数是多少?

        :8位指数位全为1,则浮点数为正负无穷大、NaN(Not a Number)中之一,因为尾数位等于0,所以这代表的浮点数为无穷大,因为符号位为1,所以表示的是负无穷大。

        例子4:寄存器\内存里的32位内容是 0b0_00000000_10000000000000000000000,这代表的浮点数是多少?

        :8位指数位全为0,且尾数不为0,所以这是一个非规格化数,其值为2^{-126}(0b0.1) = 2^{-126}(2^{-1}) = 2^{-127},可以注意到,非规格化浮点数都是绝对值很小的数。

1.3 单精度浮点数的有效位数

        教科书上说,单精度浮点数具有6~7位有效位数(十进制),这是怎么来的呢?

        下图为编写这篇博客时百度百科对此的解释:

        

图 百度百科对单精度浮点数解释

        这个解释明显是错误的,例如定义浮点数134,217,728,其有效位数为9位,那么计算机会将其四舍五入嘛?

       

        实际上并不会,仍然保持9位有效数字。那么6到7位的有效数字是怎么来的呢?

        其实上面的数字134,217,728是精心设计过的,实际上134,217,728到134,217,744(左闭右开区间)的范围的实数用单精度浮点数表示都是134,217,728(0x4D 00 00 00)

原因如下:

        根据1.2节的 图 单精度浮点数值计算,可以知晓,尾数最多的数字应为规格化数,其二进制有效位数最大为 (1 + 23)位,对应十进制数 2^{24} = 1677218,介于10^{6}10^{7}之间,也就是教科书上说的6~7位有效数字。

        实际上,应该理解为单精度浮点数具有6~7位的可信位数,也就是说这个数字从左侧第一个不为0的位开始,至少可以保证向右6~7位是正确可以信赖的,再往后的位数就不能保证是对的了。

        例如,之前提到的将134,217,743赋值给单精度浮点数变量,变量值会变为134,217,728,也就是说前7位'134,217,7XX'(不包括XX)是正确可信的,后两位'28'是错误的,不可信的。

大数吃小数

        大数吃小数是指一个很大的数,加减一个很小的数,其数值不变。例如134217728 + 1 =  134217728 ;现在我们知道这个原理就是单精度浮点数有效(可信)位数只有6~7位,同样的双精度或其他精度的浮点数有他们各自的有效位数。只要相加减的两个单精度数的数量级差距超过了10^{7},就会出现大数吃小数的现象(浮点数加减运算时,较小的数要向较大的数的阶码对齐,对应较小数的尾数就要在寄存器中右移,当右移溢出位为1时,导致损失精度,也即有效位数损失了,也即可信位数损失了)。

        从事算法相关领域落地实现时,忽略了这一点,会造成严重的错误(134217728 + 1 - 134217728  = 0,表现为错误),而不是误差(134217728 + 1 = 134217728 ,表现为精度不够)

  • 35
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值