C语言之数据在内存中的存储(2),浮点数在内存中的存储


目录

前言

一、引例

二、浮点型在内存中的存储

三、浮点数在内存中的存和取过程

1.浮点数的存储过程

2.浮点数的取过程

四、引例解析

总结



前言

        想知道浮点数在内存中是如何存储的吗,本文就告诉你答案,虽然一般情况题目还是面试涉及到浮点数在内存中的存储很少,但是了解其存储机制有利于加深我们对C语言的理解,修炼我们的内功。


❤️感谢支持,点赞关注不迷路❤️


 

 

一、引例

我们看以下代码:

#include <stdio.h>

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\n", *pFloat);

	return 0;
}

运行结果:

发现:我们观察到,将整数9以浮点型打印时为0.000000,将浮点型9.0以整形打印时是一个较大的数字。这一点就可以说明整形与浮点型在内存中的存储形式是不同的。


二、浮点型在内存中的存储

我们知道整数在内存中是以补码的形式储存的,那么浮点数是怎么存储的呢?

根据国际标准IEEE(电气和电子工程协会)754,任意一个⼆进制浮点数V可以表示成下面的形式:

举例:浮点数5.5用以上形式如何表示:

  1. 首先5.5翻译成二进制为 101.1。
  2. 然后就可以改写成以下形式:
  3. 这时候,M就是1.011,E就是2,S自然为0


然后,只需要将S、M、E这三个数存储到内存中,就可以储存一个浮点数了,那么这三个数是如何在内存中存放的呢?

IEEE 754规定:

  • 对于32位的浮点数(float),最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数
  • 字M 对于64位的浮点数(double),最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M

注意:不管怎样,内存中存储的还是补码


  

三、浮点数在内存中的存和取过程

1.浮点数的存储过程

IEEE 754对有效数字M和指数E,还有一些特别规定。

M的存储过程:前面用101.1举例,可以写成类似科学计数法的形式。1<=M<2,也就是说,M可以写成 1.xxxxxx 的形式,其中 xxxxxx 表表示小数部分。那么就有以下规定:

IEEE 754规定,在计算机内部保存M时,默认这个数的第⼀位总是1,因此可以被舍去,只保存后面的 xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保存24位有效数字。

E的存储过程:指数E,情况就比较复杂首先,E为一个无符号整数(unsigned int),这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的。E又是无符号整数,所以规定:

IEEE754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E是 10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

举例:浮点数(float)5.5,二进制位:101,1

  1. S:0,E:2,M:001
  2. 但是E存入内存时(float)要加上127等于129
  3. 结果就是 0 10000001 01100000000000000000000
  4. 注意:M后不够是补0的
  5. 0100 0000 1011 0000 0000 0000 0000 0000翻译为16进制为0x40 b0 00 00
  6. 然后我们在VS中调试观察,验证以下
  7. 因为VS是小端存储,所以是倒着存,结果一致


2.浮点数的取过程

这里主要是指数E从内存中取出还可以再分成三种情况:

1.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 00000000000000000000

2.E全为0(特殊情况)

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

比如1.0*2的负127次方,这个数无限接近于0,所以M读取时不再加上1,并且指数读取时是减126而不是127,因为M的整数位1被移到了小数部位,所以内存中为0 00000000 00000000000000000000000,读取时就是0.000000

3.E全为1(特殊情况)

这时,浮点数指数 E 等于128,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);

我们可以简单算一下,2的32次方大约42亿,那么4个42移相乘,那数字将会非常大。


四、引例解析

引例中的结果:

我们来一步一步分析:

  1. 首先 int n = 9,它在内存中的补码为:00000000 00000000 00000000 00001001。以%d打印肯定是9没毛病。
  2. 然后通过指针把它当做浮点型打印,这时编译器就会将n的补码以浮点数的格式进行读取,float为32个比特位,可以写成0 00000000 00000000000000000001001。
  3. 这里 E 的部分全为0,对应了上文第二种情况,E将无限接近于0,读取出来就是,0.9*2的负126次方,等于0.00000...9,而编译器默认打印小数点后6位,因此结果才为0.000000
  4. 通过指针将n的空间存的值修改为9.0,而9.0将会以32位浮点型的格式存储到内存中,9.0翻译为二进制为:1001.0,变为科学计数法为:1.001*2^3,那么S:0,E:3,M:1.001
  5. E存入内存要加上127等于130,二进制为:10000010,因此9.0存入内存的二进制为:0 10000010 00100000000000000000000
  6. 将 01000001000100000000000000000000以整形的格式读取时就为:
  7. 以浮点型%f读取就是正常9.0

所以我们在拿到一个数据时,非特殊一定要以正确的格式读取,否则就不是你想要的数字


总结

        以上就是本文的全部内容,希望对你有所帮助。

### 关于ArcGIS License Server无法启动的解决方案 当遇到ArcGIS License Server无法启动的情况,可以从以下几个方面排查并解决问题: #### 1. **检查网络配置** 确保License Server所在的计算机能够被其他客户端正常访问。如果是在局域网环境中部署了ArcGIS Server Local,则需要确认该环境下的网络设置是否允许远程连接AO组件[^1]。 #### 2. **验证服务状态** 检查ArcGIS Server Object Manager (SOM) 的运行情况。通常情况下,在Host SOM机器上需将此服务更改为由本地系统账户登录,并重启相关服务来恢复其正常工作流程[^2]。 #### 3. **审查日志文件** 查看ArcGIS License Manager的日志记录,寻找任何可能指示错误原因的信息。这些日志可以帮助识别具体是什么阻止了许可服务器的成功初始化。 #### 4. **权限问题** 确认用于启动ArcGIS License Server的服务账号具有足够的权限执行所需操作。这包括但不限于读取/写入特定目录的权利以及与其他必要进程通信的能力。 #### 5. **软件版本兼容性** 保证所使用的ArcGIS产品及其依赖项之间存在良好的版本匹配度。不一致可能会导致意外行为完全失败激活license server的功能。 #### 示例代码片段:修改服务登录身份 以下是更改Windows服务登录凭据的一个简单PowerShell脚本例子: ```powershell $serviceName = "ArcGISServerObjectManager" $newUsername = ".\LocalSystemUser" # 替换为实际用户名 $newPassword = ConvertTo-SecureString "" -AsPlainText -Force Set-Service -Name $serviceName -StartupType Automatic New-ServiceCredential -ServiceName $serviceName -Account $newUsername -Password $newPassword Restart-Service -Name $serviceName ``` 上述脚本仅作为示范用途,请依据实际情况调整参数值后再实施。 --- ###
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值