看完就等于拿捏浮点数在内存中的储存了

简介: 看完就等于拿捏浮点数在内存中的储存了

诸君又该学习了,今天我们继续来一睹浮点数的奥妙真容。

经过前面文章对整形提升相关的解释,我们都对整形和字符在内存空间上的储存已经有了大概的认知,那么现在我们就来好好讲讲浮点数在内存中的储存规则。


浮点数与整形储存的不同

#include<stdio.h>
 
int main()
{
  int a = 9;
  float* p = (float*)&a;
 
  printf("%d\n", a);
  printf("%f\n", *p);
 
  *p = 9.0;
  printf("%d\n", a);
  printf("%f\n", *p);
 
  
  return 0;
}

那么我们现在可以思考一下这个结果证明了什么呢?

是不是就是证明了,我们浮点数和整形数据在内存中的储存方式是不一样的,而且float类型和int整形所占字节都是4个字节,这样更能体现int和float内存储存数据的不一样。那么下面我将展开说一下float在内存中到底如何储存数据的。

浮点数在内存中的储存规则

首先这里我们先看一个公式,这使我们等下更好的理解这块


V   =  (−1) ^S *M * 2^E,那这里我们可以来来看看这里的S,M,E到底是什么?


(-1)^S    用来取决这个浮点型数据的正负,如果为0则为正数,如果为1则为负数。


M和E     即为一个大于1小于2的数,即1<=M<2,那么后面的2^E也很容易知道了,其为一个像科学计数法似的指数。如:5.5转化二进制浮点型表示------>101.1=1.011*2^2  那么此时M=1.001,E=2,S=0


我们这里直接甩图,让大家直接看清楚,浮点型数据中32位bit是怎么储存,打印时又要怎么读取呢。


float型

double型

这样一看诸君是否就清楚许多,恍然大悟呢,那么先别急,这里还需讲一个知识点。


浮点数的存储过程:

浮点数存的过程 IEEE 754 对有效数字M和指数E,还有⼀些特别规定。 前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中 xxxxxx 表示小数部分。 IEEE 754 规定,在计算机内部保存M时,默认这个数的第⼀位总是1,因此可以被舍去,只保存后面的 xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第⼀位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保 存24位有效数字。


至于指数E,情况就比较复杂 首先,E为⼀个无符号整数(unsigned int) 这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,我 们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上 ⼀个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E是 10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。


总结:计算机储存的M是直接省略整数为的1的,对于指数E我们在其基础上加上127或是1023在存取到计算机内存中,至于是加上哪个看是单精度float还是double。


下面我们看一个例子:


我们继续拿float a=5.5这个数来举例。


这里按照上面的说法。5.5为正数,那么S=0。


然后将5.5换成二进制=101.1,在换成科学计数法=1.011*2^2,此时M=1.011,然后在计算机中储存时把整数为的1,暂时舍去,在取出来时在加回去。那么此时计算机中的


M=01100000……(23bit),然后到我们这里的E=2。再按照之前的说法在这基础上加上中间数127在储存在计算机中,那么此时计算机中的E=2+127=129,转换为二进制=10000001


然后a在计算机中的储存为0 10000001 01100000000000000000000


然后二进制表示为40 b0 00 00,


那么是否就是这样呢,我们来用计算机来验证一下

这里VS是小端储存所以我们就看到如图的储存方式


浮点数取的过程


E不全为0或不全为1 这时,浮点数就采⽤下⾯的规则表⽰,即指数E的计算值减去127(或1023),得到真实值,再将有效 数字M前加上第⼀位的1。 ⽐如:0.5 的⼆进制形式为0.1,由于规定正数部分必须为1,即将⼩数点右移1位,则为1.0*2^(-1),其 阶码为-1+127(中间值)=126,表⽰为01111110,⽽尾数1.0去掉整数部分为0,补⻬0到23位 00000000000000000000000,则其⼆进制表⽰形式为:


0 01111110 00000000000000000000000


E全为0 这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,而是还 原为0.xxxxxx的⼩数。这样做是为了表⽰±0,以及接近于0的很小的数字。


0 00000000 00100000000000000000000


E全为1 这时,如果有效数字M全为0,表示±⽆穷大(正负取决于符号位s)


0 11111111 00010000000000000000000

最后再回到开始的代码:

#include<stdio.h>
 
int main()
{
  int a = 9;
  float* p = (float*)&a;
 
  printf("%d\n", a);
  printf("%f\n", *p);
 
  *p = 9.0;
  printf("%d\n", a);
  printf("%f\n", *p);
 
  
  return 0;
}


这里我们一步一步拆分,在这段代码中int a=9.则是按整形的方式来储存,则二进制在计算机中储存为 00000000000000000000000000001001,那么在进行这么(printf("%f\n", *p);)打印时我么会把他当作浮点数的形式进行取出,此时S=0,E为全0按照上面的取出规则


E=1-127。计算机中的M=00000000000000000001001,在加上存之前舍去的1,则M=100000000000000000001001,这么计算起来M*2^-126,非常小,接近于0,所以打印出来一个


0.000000


然后到第三行打印结果,我们将9已浮点数的形式储存,浮点数9.0 等于⼆进制的1001.0,即换算成科学计数法是:1.001×2^3 所以: 9.0  =  (−1)   ^ 0  *(1.001)  ∗  2^3 , 那么,第⼀位的符号位S=0,有效数字M等于001后⾯再加20个0,凑满23位,指数E等于3+127=130, 即10000010 所以,写成⼆进制形式,应该是S+E+M,即0 10000010 001 0000 0000 0000 0000 0000


那么按照整形的方式取出来就是一个很大的数,即1091567616


文章已到末尾,诸君对浮点数储存懂否。

目录
相关文章
|
5月前
|
存储
浮点数在内存中的存储
浮点数在内存中的存储
52 0
|
5月前
|
存储 C语言
C语言第二十九弹---浮点数在内存中的存储
C语言第二十九弹---浮点数在内存中的存储
|
存储 C语言 C++
C语言之数据的存储2(浮点数在内存中如何存储,如何输出,查看不同类型数据在内存中表示的范围的方法,十进制浮点数转化为二进制的方法)
C语言之数据的存储2(浮点数在内存中如何存储,如何输出,查看不同类型数据在内存中表示的范围的方法,十进制浮点数转化为二进制的方法)
121 0
|
4月前
|
存储 C语言
数据在内存中的储存
数据在内存中的储存
27 3
TU^
|
5月前
|
存储 C语言
C语言浮点数在内存中的存储
在C语言中,浮点数类型用float和double表示。float类型使用4个字节(32位),而double类型使用8个字节(64位)。浮点数表示的范围:float.h中定义
TU^
59 0
|
5月前
|
编译器 C语言
动态内存的管理(内存储存的god)
动态内存的管理(内存储存的god)
33 0
|
5月前
|
存储
整数和浮点数在内存中存储
整数的2进制表⽰⽅法有三种,即原码、反码和补码。
50 0
|
5月前
|
存储 Windows 容器
浮点数在内存中的存储
浮点数在内存中的存储
30 2
|
5月前
|
存储 编译器 C语言
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
|
5月前
|
存储 C语言
[C语言]数据在内存中的存储(浮点数篇)
[C语言]数据在内存中的存储(浮点数篇)
73 0