IEEE754 浮点数存储分析

        浮点数数据在计算机中的是按照特定的编码格式进行存储的,下面我们就以float数据-20.5来分析一下浮点数的存储格式。 

目录

结构组成

符号码

指数码

尾数码

十进制转化为浮点数

浮点数范围

绝对值最小值

绝对值最大值

 指数码真码特殊值

浮点数精度问题


结构组成

浮点数结构分为三个部分:符号码、指数码、尾数码。

 IEEE 754 标准分 3 个类型的浮点数:分别是 短浮点数 float,长浮点数 double,临时短浮点数 long double,存储结构如下:

符号码

符号码占用1个bit,占用最高位,对于-20.5数值,符号位为1,代表为负数。对于浮点数符号判断,可以使用std::signbit进行判断,详细见:std::signbit - cppreference.com

指数码

指数码是最为复杂的字段,指数码表示尾数码偏移的二进制的位数。在 IEEE 754 浮点数标准中,指数码是用移码表示的,移码的计算方式:移码 = 真值 + 偏置值;在浮点数标准中偏置值为 2^(8-1)-1 = 127。如图所示,131=127+4;因此-20.5的指数码为4。

尾数码

在 IEEE 754 浮点数标准中,尾数码部分采用原码表示,且尾数码隐含了最高位 1,在计算时我们需要加上最高位1,即 1.M,我们通过一个例子来表示:

1.01001B = 1 + 0*{2^{-1}} + 1*{2^{-2}} + 0*2^{-3}+ 0*2^{-4} + 1*2^{-5} =1.28125

1.01001B = 1 + 0*0.5 + 1*0.25 + 0*0.125+ 0*0.0625 + 1*0.03125 =1.28125

十进制转化为浮点数

接下来咱们就使用-20.5D看看怎样一步一步转化为内存中显示的方式的。

       -20.5D分为三个部分:-20.5=-1.0*(20+0.5)

       -1.0先不进行处理,20D转化为二进制为10100B,0.5D转化为二进制为0.1B,因此20.5D转化为二进制为:10100.1B,将整数部分转化为1,将二进制数据右移4位:1.01001B*2^{4}=10100.1B隐藏整数部分的1,因此尾数码为0.01001B。指数为4,转化为偏移码:4+127=131D,转化为二进制:10000011B。

-20.5D转化为浮点数进行存储时为:符号码1<<31+指数码(10000011B)<<23 + 尾数码(01001000000000000000000B) =11000001101001000000000000000000B。

数值计算value = -1.0(符号位)*2^{4}(指数位:2的4次方)*1.28125 (位数:1(被隐藏)+0.28125)= -20.5;

浮点数范围
  • 绝对值最小值

       IEEE 754 单精度浮点型表示的的最小绝对值:尾数码全为 0 ,阶码真值为 -126D(对应的移码为 0000 0001B),此时整体的值为 1.0B * 2^(-126D)

  • 绝对值最大值

     IEEE 754 单精度浮点型表示的的最大绝对值:尾数码全为 1 ,阶码真值为 127D(对应的移码为 1111 1110B),此时整体的值为 1.111…B * 2^(127D)

  •  指数码真码特殊值

一般我们正常探讨的指数码真码区间是 -126D ~ 127D,而真值 -127D 的阶码为 0000 0000B,真值 128D 的阶码为 1111 1111B。

  • 指数码真值为 -127

     当指数码全为 0 ,尾数不全为 0,表示 非规格化小数 ,用来表示比最小绝对值还要小的数,即

    尾数码 隐含的最高位不是 1,而是 0;

    当指数码全为 0 ,尾数全为 0,表示 真值 +/- 0 ;

  • 指数码真码128

当阶码全为 1 ,尾数全为 0,表示 正负无穷大 +/- ∞

当阶码全为 1 ,尾数不全为 0,表示非数值 NaN(Not a Number)

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
    float a = 0.11;
    float b = -20.5;
    float c = -0.00000001234567;
    float d = -1.123456789;
    float e = 12.123456789;
    float f = -123.123456789;
    float g = -0.0;
    float h = 0.0;

    int size = sizeof (b);
    bool sigB = std::signbit(b);
    bool sigE = std::signbit(e);
    bool sigG = std::signbit(g);
    bool sigH = std::signbit(h);
    std::cout << "sigB: " << sigB << " , sigE : " << sigE << std::endl;
    std::cout << "sigG: " << sigG << " , sigH : " << sigH << std::endl;
    return 0;
}

浮点数精度问题

由上图可知,对于float类型数据来说,可以表示7位精度的数据,并不是表示小数点后7位数据。std::numeric_limits<float>::epsilon()  EPSILON指的是浮点数可表示的最小值,有没有比EPSILON更小的数呢?答案是肯定的。EPSILON被规定为是最小误差,换句话说就是使得EPSILON+1.0不等于1.0的最小的正数,也就是如果正数d小于EPISILON,那么d和1.0相加,计算机就认为还是等于1.0,这个EPISILON是变和不变的临界值。EPSILON被规定为是最小误差的前提是EPSILON加上一个大于1.0的数与不加EPSILON是相等的,但是如果是两个EPSILON相加肯定大于EPSILON。

参考资料:

IEEE754 浮点数:简读+案例=秒懂_ieee754浮点数的计算-CSDN博客

IEEE754标准: 一 , 浮点数在内存中的存储方式 - 知乎

std::signbit:std::signbit - cppreference.com

std::numeric_limits的使用:std::numeric_limits的使用_std::numeric_limits<float>::epsilon()-CSDN博客

IEEE-754 Floating Point Converter:IEEE-754 Floating Point Converter

  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值