杂谈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 。

相关推荐
jiao_mrswang1 小时前
leetcode-18-四数之和
算法·leetcode·职场和发展
qystca1 小时前
洛谷 B3637 最长上升子序列 C语言 记忆化搜索->‘正序‘dp
c语言·开发语言·算法
薯条不要番茄酱1 小时前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
今天吃饺子1 小时前
2024年SCI一区最新改进优化算法——四参数自适应生长优化器,MATLAB代码免费获取...
开发语言·算法·matlab
是阿建吖!1 小时前
【优选算法】二分查找
c++·算法
王燕龙(大卫)1 小时前
leetcode 数组中第k个最大元素
算法·leetcode
不去幼儿园2 小时前
【MARL】深入理解多智能体近端策略优化(MAPPO)算法与调参
人工智能·python·算法·机器学习·强化学习
Mr_Xuhhh2 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
盼海3 小时前
排序算法(五)--归并排序
数据结构·算法·排序算法
网易独家音乐人Mike Zhou6 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot