杂谈c语言——6.浮点数的存储

1.浮点数在内存中的存储

常⻅的浮点数:3.14159、1E10等,浮点数家族包括:float、double、long double 类型。 浮点数表⽰的范围: float.h 中定义

1.1 练习

复制代码
#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("num的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
	return 0;
}

输出什么呢?

答案是:

1.2 浮点数的存储

上⾯的代码中, num 和 *pFloat 在内存中明明是同⼀个数,为什么浮点数和整数的解读结果会差别 这么⼤?

要理解这个结果,⼀定要搞懂浮点数在计算机内部的表⽰⽅法。 根据国际标准IEEE(电⽓和电⼦⼯程协会)754,任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:

举例说明:

5.5(十进制) ==101.1(二进制),转换为二进制的科学计数法为1.011*2的2次方

就相当于**(-1)的0次方*1.011*10的2次方**

所以:

S==0;

M==1.011;

E==2;

浮点数的存储,就是存储S,M,E相关的值 !!!!!!

IEEE754规定:

1.对于32位的浮点数最⾼的1位存储符号位S接着的8位存储指数E剩下的23位存储有效数字M

float类型浮点数内存分配

2.对于64位的浮点数最⾼的1位存储符号位S接着的11位存储指数E剩下的52位存储有效数字M

double类型浮点数内存分配

2.浮点数存的过程

1.EEE754对有效数字M指数E,还有⼀些特别规定。

前⾯说过, 1≤M<2,也就是说,M可以写成 1.xxxxxx 的形式,其中 xxxxxx 表⽰⼩数部分。 IEEE754规定,在计算机内部保存M时,默认这个数的第⼀位总是1,因此可以被舍去(即1不存储)只保存后⾯的 xxxxxx部分!!!!!!!!!!!!!!!!!!!!!!!!!!!。⽐如保存1.01的时候,只保存01,等到读取的时候,再把第⼀位的1加上去。

这样做的⽬ 的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保 存24位有效数字。

2.⾄于指数E,情况就⽐较复杂

⾸先,E为⼀个**⽆符号整数(unsigned int)**

这意味着,1.如果E为8位,它的取值范围为0~255;2.如果E为11位,它的取值范围为0~2047。但是,我 们知道,科学计数法中的E是可以出现负数的

举例:

0.5(十进制)==0.1(二进制)==1.0*2的**-1次方,这就产生了负数!!!!**

所以IEEE754规定,存⼊内存时E的真实值必须再加上 ⼀个中间数:

1.对于8位的E,这个中间数是127

2.对于11位的E,这个中间数是1023

⽐如,2^10的E是 10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

3.浮点数取的过程

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

1.E不全为0或不全为1

这时,浮点数就采⽤下⾯的规则表⽰,

1.指数E的计算值减去127(或1023),得到真实值

2.再将有效 数字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

2.E全为0

这时,浮点数的指数E等于1-127(或者1-1023)!!!!!!!!!!!!!!!即为真实值,有效数字M不再加上第⼀位的1,⽽是还 原为0.xxxxxx的⼩数

这样做是为了表⽰±0,以及接近于0的很⼩的数字。!!!!!!!!!!!!!

0 00000000 00100000000000000000000

3.E全为1

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

1 0 11111111 00010000000000000000000

4.题目解析

复制代码
#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("num的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
	return 0;
}

1.n在内存中的补码是

0000 0000 0000 0000 0000 0000 0000 1001

但是pfloat取数据的时候是按照浮点数的方式去取的,即

⾸先,将 9 的⼆进制序列按照浮点数的形式拆分,得到

1.第⼀位符号位s=0

2.后⾯8位的指数E=00000000

3.最后23位的有效数字M=00000000000000000001001
V=(-1)^0 × 0.00000000000000000001001×2^(-126)=1.001×2^(-146)

E全是0符合情况2,所以输出为0.0000000

  1. pfloat存储9.0 即换算成科学计数法是:1.001×2^3

1.第⼀位的符号位S=0

2.有效数字M等于001后⾯再加20个0,凑满23位

3.指数E等于3+127=130, 即10000010

所以,写成⼆进制形式,应该是S+E+M,即

0 10000010 001 0000 0000 0000 0000 0000

这个32位的⼆进制数,被当做整数来解析的时候,就是整数在内存中的补码,原码正是 1091567616 。

相关推荐
s砚山s2 分钟前
代码随想录刷题——二叉树篇(十三)
数据结构·算法
alphaTao6 分钟前
LeetCode 每日一题 2026/1/5-2026/1/11
算法·leetcode
山上三树8 分钟前
详细介绍 C 语言中的 #define 宏定义
c语言·开发语言·算法
麻雀12322 分钟前
win7中编译qemu-system-arm,仿真arm设备
c语言·eclipse
黎雁·泠崖22 分钟前
二叉树知识体系全梳理:从基础到进阶一站式通关
c语言·数据结构·leetcode
山上三树23 分钟前
详细介绍 C/C++ 中的内存泄漏
c语言·c++
AI科技星23 分钟前
引力与电磁的动力学耦合:变化磁场产生引力场与电场方程的第一性原理推导、验证与统一性意义
服务器·人工智能·科技·线性代数·算法·机器学习·生活
Legendary_00825 分钟前
LDR6020:单C口可充可放电PD协议芯片,开启USB2.0数据传输新体验
c语言·开发语言
蜕变菜鸟25 分钟前
JS的Object.keys()和sort()排序的用法
数据结构·算法
源代码•宸26 分钟前
Golang基础语法(go语言error、go语言defer、go语言异常捕获、依赖管理、Go Modules命令)
开发语言·数据库·后端·算法·golang·defer·recover