float在内存中的存储方式

float 在内存中的储存方式


C语言中,对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用32bit, double数据占用


64bit,我们在声明一个变量float f= 2.25f的时候,是如何分配内存的呢?如果胡乱分配,那世界岂不是乱套了么,其实不论是


float还是double在存储方式上都是遵从IEEE的规范的,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53。


无论是单精度还是双精度在存储中都分为三个部分:

1.                   符号位(Sign) :0代表正,1代表为负

2.                   指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储

3.                   尾数部分(Mantissa):尾数部分


其中float的存储方式如下图所示:



 

而双精度的存储方式为:



  R32.24和R64.53的存储方式都是用科学计数法来存储数据的,比如8.25用十进制的科学计数法表示就为:8.25*10^0 ,而120.5


可以表示为:1.205*10^2 , 这些小学的知识就不用多说了吧。而我们傻蛋计算机根本不认识十进制的数据,他只认识0,1,所以在计算机存储中,首先要将上面的数更改为二进制的科学计数法表示,8.25用二进制表示可表示为1000.01,我靠,不会连这都

不会转换吧?那我估计要没辙了。120.5用二进制表示为:1110110.1用二进制的科学计数法表示1000.01可以表示为1.0001*2^3 ,


1110110.1可以表示为1.1101101*2^6 ,任何一个数都的科学计数法表示都为1.xxx* 2^n, 尾数部分就可以表示为xxxx,第一位都是1嘛,干嘛还要表示呀?可以将小数点前面的1省略,所以23bit的尾数部分,可以表示的精度却变成了 24bit,而对于指数部分,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127-128了,所以指数部分的存储采用移位存储,存储的数据为元数据+127,


下面就看看8.5和120.5在内存中真正的存储方式。

 首先看下8.5,用二进制的科学计数法表示为:1.0001*2^3

按照上面的存储方式,符号位为:0,表示为正,指数位为:3+127=130 ,位数部分为,故8.5的存储方式如下图所示:


而单精度浮点数120.5的存储方式如下图所示:


下面说下取值范围和精度:
取值范围看指数部分:
float是有符号型,其中,8位指数位,2^8=(-128—127),因此实际的范围是-2^128—2^127,约为-3.4E38—3.4E38


同理double范围约是-1.7E308—1.7E308,
精度是看尾数部分:
float尾数位23位,2^23=8.3E6,7位,所以不同的编译器规定不同,有些是7位,有些8位
double尾数52位,2^52=4.5E15,15位,所以double的有效位数是15位


补充一下:小数是如何转换成二进制的,以首先将13.625转化成二进制为例子:
整数部分:13 ------>1101
小数部分:小数部分乘2取整,然后从前往后读。

     0.625*2 = 1.25        取整      1

     0.25*2   = 0.5          取整      0

     0.5*2    = 1             取整      1

     所以小数部分的二进制  101

所以13.625转换成二进制:1101.101

Data:2018/12/13 补充一下浮点型的几点知识
我记得之前在数据类型里面说过一个概念,棱子,也叫模子
我们经常说取模,取模,也是这个道理
比如一个
char i = 350;
那么这个i 取模后,肯定没有350,因为i的模子大小char,char的模子大小是
0~255 - 一共256个数
所以上面的 printf("%d",i) 输出的应该是 350 - 256 = 94

但是浮点数是不支持模运算的,所以引进了溢出这样的说法

nan = not a number =表示不是一个实数
nan 不等于任何浮点数值,包括它自身在内;即它与任何数比较均返回false。
inf = Infinity 无穷大 (包括正数无穷大和负数无穷大)
我们数学里面有实数,所以C语言里面有了浮点型,想用浮点型来表实实数,但是如果这个实数的小数点无限长,就不可能真实的表达这个实数,所以,只能近似的表示实数。

列举man和inf的几个情况

x / 0.0 = +inf 当 x > 0.0
x / 0.0 = -inf 当 x < 0.0
0.0 / 0.0 = nan
0.0*∞ = nan
∞ * ∞ = nan
(+inf)+ (+inf ) = inf
(+inf)+ (- inf ) = nan
x /+∞ = +0.0
x /-∞ = - 0.0
我们用一个C程序验证一下

#include<stdio.h>

void main(void)
{
float x = 1.2;

printf("%f\n",x/0.0);
printf("%f\n",-x/0.0);
printf("%f\n",0.0/0.0);
printf("%f\n",0.0*(x/0.0));
printf("%f\n",(x/0.0)*(x/0.0));
printf("%f\n",x/0.0 + x/0.0);
printf("%f\n",x/0.0 - x/0.0);
printf("%f\n",x/(x/0.0));
printf("%f\n",x/(-x/0.0));

}
输出

如何实现一个通用的判断来判断数据是inf或者nan呢?
首先,对于 Nan,可以用下面的代码实现:

bool IsNumber(double x)
{
// 这里的比较操作看上去总是会得到 true
// 但有趣的是对于 IEEE 754 浮点数 NaN 来说总会得到 false!
return (x == x);
}
而下面的代码可以判断一个浮点数是否是有限的(finite, 即既不是 NaN 又不是 infinite):

bool IsFiniteNumber(double x)
{
return (x <= DBL_MAX && x >= -DBL_MAX);
}
//其中,DBL_MAX 是 <float.h> 中预定义的常量。
把上面两个函数结合起来,还可以实现一个浮点数是否是 Inf 的判断。

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值