什么?浮点型数据的存储原来这么简单!

文摘   科技   2023-05-14 18:00   安徽  

浮点型数据,即float型数据。不同于整数型数据再内存中的简单存储方式,相对而言较难理解,有很多同学在刚接触数据类型的时候都会表示一脸懵逼,根本不理解呀!



但其实只要特别关注一下,你就能明白其中的奥秘并不困难。今天小编就以“浮点数在内存中的储存方式”为主题,与大家一起探讨~




首先,什么是浮点型数据?


浮点型数据是用来表示具有小数点的实数的。为什么在C语言中把实数称为浮点型数呢?在C语言中,实数是以指数形式存放在存储单元中的。


一个实数表示为指数可以有不止一种形式,如3.1459可以表示为:

3.14159×100,0.314159×101,0.0314159×102,31,14159×10-1,或314,159×10-2等。可以看到:小数点的位置是可以在314159几个数字之间、之前或之后(加0)浮动的,只要在小数点位置浮动的同时改变指数的值,就可以保证它的值不会改变。由于小数点位置可以浮动,所以实数的指数形式称为浮点数。




浮点型数据与整数型数据的差别


对于浮点类型数据,我们最需要明白一点就是:浮点数和整数的编码方式差异巨大。举个例子:


#include

int main()

{

       int a = 9;

       float *pFloat = (float *)&a;

       printf("%f\n",*pFloat);


       float b = 9.0;

       float *p = &b;

       printf("%f\n",*p);


       return 0;

}


运行结果:




浮点数据的存储方式


从以上结果得知浮点数的存储方式和整数是不一样的。那么,浮点数据是如何存储的呢?根据国际标准IEEE(电子与电气工程协会)规定,任何浮点数的二进制数存储都要遵循以下公式进行转换:


NUM = (-1) ^ s * M * 2 ^ E

来来来我们解释一下:

       S : 当S为1时,表示为负浮点数,当S为0时,表示正浮点数

       M: 表示有效数 ,1<=M<2

      2^E: 表示指数


可能有些同学看到上面的公式已经心情开始浮躁了,但是不要慌,稳住,我们能赢!



想看懂上面的内容,首先了解一下浮点在内存的存储方式。如下图所示:



那么问题来了,s表示符号位,0为正数,1为负数,那好办,这个位要么0,要么1,当然负数的存储方式是不一样的,本文讨论的是正浮点的情况,浮点的存储方式,所以s为0。那e是什么呢?这八位存储的内容又是什么?


我们先确定e(指数域的二进制表示)是如何得来的,计算的e的结果需要用以下公式:


e = E + Bias

E : 从上面公式知道E为指数

E的计算方式如下:

       以135.5这个浮点数为标本

    (1) 取整数135转换为二进制(不知道自己用计算器或者百度)为10000111

    (2) 取小数0.5转换为二进制(方法为小数乘2取整数,不懂百度)为 0.5 * 2 = 1.0,所以小数位1,

          举个例子:如果小数是0.375,计算方式为

            0.375 * 2 = 0.75         0

            0 . 75 * 2 = 1.5             1

            0.5 * 2 = 1.0                 1

            所以0.375转换为二进制数值为 0.011 就是 011


  (3)那么可以得出135.5的二进制为10000111.1

  (4)将这个数值套进公式

    10000111.1 = (-1)^0 * (1.00001111)*2 ^ 7

   所以得出E的值为7


Bias : 是一个等于2^k-1 – 1的偏置值(k为指数域位数,对于32位浮点数是8,对于64位浮点数而言是11,因为我的是32位系统,所以k值为8),通过此方法可以得出Bias的值为

2^8-1 – 1 = 127


那么e = 7+127 = 134 转换为二进制为 10000110


M :小数部分 , 从上方可以得出结果为 00001111


好了,这样就可以将  s ,     e ,                      M

                                  0       10000110      00001111 000000000000000

共32位.

所以得出结果,135.5在内存中的存储方式如下

 0000 0000 低地址    0

1000 0000     -128(最高位1为负数)

0000 0111       7

0100 0011 高地址  67


嗯,接下来验证奇迹的时刻来了,写个代码测试以下


#include


int main()

{

       float m = 135.5;

       char *a = (char *)&m;


       printf("0x%p = %d\n",a,*a);

       printf("0x%p = %d\n",a+1,*(a+1));

       printf("0x%p = %d\n",a+2,*(a+2));

       printf("0x%p = %d\n",a+3,*(a+3));


       return 0;

}


运行结果如下:


从结果可以得出我们的认证是正确的,哦,对了,还可以知道小编的系统是小端模式。最后奉上小编分析的鬼画符。

⬇⬇⬇

*小编的测试系统为32位的ubuntu 14.04



以上就是今天所有的内容啦

如果大家有什么关于浮点数的问题,欢迎在评论区留言

我们下期再见~





好课
推荐



华中科技大学教授杨文玉 | 机器人运动学中的几何与代数问题



合肥工业大学教授都海波|飞行器姿态控制



重庆大学教授陈锐|3D视觉及其在协作机器人中的应用



精品课推荐 | 经典机电控制系统开发(以倒立摆为例)



南京大学教授、博导陈春林|强化学习及其在机器人中的应用



精品课|移动抓取机器人的建模、仿真与实物控制



精品课推荐| 基于模型设计开发协作机器人方法与技术



限时推出|开源两轮智能平衡移动机器人电控系统开发课程



伺服系统及其控制原理概述




点击“阅读原文”,和小谷一起学习!

深谷讲坛
专注人工智能与机器人创新人才培养
 最新文章