C语言知识小科普之浮点型是如何存储的

本文详细解释了C语言中浮点数如何根据IEEE754标准在32位和64位系统中进行内存存储,包括符号位、指数位和有效数字的处理,以及浮点数取值的规则和示例代码的解析。
摘要由CSDN通过智能技术生成

不知道大家在写C语言的时候有没有好奇过,浮点型的数据在内存中是如何存储的呢?

我们可能只知道在32位平台下float类型占四个字节,double类型占八个字节,像下图一样。

浮点数是怎么存放的呢?

相比于整型和字符型而言,浮点型的存储要复杂一点。

对于浮点型的存储标准,根据国际标准IEEE(电气电子工程师学会)754的定义:

任何一个浮点数都可以写成 (-1)^S*M*2^E其中

  • (-1)^S表示符号位,S=0 为正数 ,S=1 为负数;
  • M表示有效的数字,1 <= M < 2;
  • 2^E表示指数位

看不懂没关系,举个例子:

  •  5.0 = 101.0 = 1.01*2^2

        5.0这个浮点数写成二进制的形式是 101.0 再将 101.0 转换成科学计数法 就是 1.01*2^2

        而它又是一个正数 所以 它的 S=0,M=1.01,E=2。

  •  9.5 = 1001.1 = 1.0011*2^3

        9.5这个浮点数写成二进制的形式是 1001.1 再将 1001.1 转换成科学计数法 就是 1.0011*2^3

        而它又是一个正数 所以 它的 S=0,M=1.0011,E=3(注意十进制小数和二进制小数的转换)

        变成这个样子以后,IEEE754规定:

  • 对于32位浮点数(float)S占1位,E占8位,M占23位

  • 对于64位浮点数(double)S占1位,E占11位,M占52位

        

此外IEEE754还做了一些规定:

  • 对于M:因为永远是 1 <= M < 2的 因此再保存的时候,只需要保存小数点后面的小数部分就可以了,最后取出来的时候再加上1。
  • 对于E:情况比较复杂。IEEE754规定E是一个无符号的整数,因此在E是8位时范围是。0~255,11位时的范围是0~2047,但是实际情况中的E是会出现负数的。所以还需要对E进行修正。对于8位的E 需要 加上 127 再存储;对于11位的E 需要 加上 1023再存储。
  • 例如 5.5 的 S=0,M=1.011,E=2,M 只取小数点后的数就是011,E=2+127=129 的二进制就是10000001,因此5.5写入内存就是 0 10000001 01100000000000000000000。

浮点数怎么取出来呢? 

分为三种情况:

E不是全0也不是全1:那就用 E-127(或1023),然后M+1 再按公式拼出原数。

E为全0:这时的E直接就等于1-127(或1-1023),M也不再加1,直接还原成0.xxxx的数表示一个特别接近与0的数。一个数加127为全0,那么E最大也是-127,而(-1)^S*M*2^-127无限接近0。

E为全1:表示一个特别特别大的数。这个也好理解,当一个数加127为全1 那么这个E至少是128,而(-1)^S*M*2^128已经非常大了。

以上就是浮点数在内存中的存取过程。

实践一下:

看看下面代码的结果是什么呢

int main()
{

	int n = 9;
	float* pFloat = (float*)&n;
	printf("n=%d\n", n);
	printf("*pFloat=%f\n", *pFloat);
	
    *pFloat = 9.0;
	printf("n=%d\n", n);
	printf("* pFloat=%f", *pFloat);

	return 0;
}

解析:

9 在计算机内存储的是 0000 0000 0000 0000 0000 0000 0000 1001;用浮点数的指针指向时就会把它解析成 0 00000000 00000000000000000001001

此时的S=0;E是00000000 直接等于1-127=-126 而M也不再加1 直接是0.00000000000000000001001根据公式就等于 +0.00000000000000000001001*2^-126

打印时,printf("n=%d\n", n):就是以整型打印,所以答案就是9;printf("*pFloat=%f\n", *pFloat):是按浮点型打印,所以结果是+0.00000000000000000001001*2^-126 近乎就是0了。 

*pFloat = 9.0,相当于以浮点型的形式存储 9.0=1001.0=1.001*2^3

那么就有S=0,E=3+127=130 也就是 10000010,M=00100000000000000000000 合起来就是01000001000100000000000000000000

修改后打印时,printf("n=%d\n", n):以整数形式打印01000001000100000000000000000000这段二进制数字就是1091567616;用计算器验证一下:

而printf("* pFloat=%f", *pFloat):以浮点数形式打印就是浮点数本身。

所以:

结果是:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值