目录
浮点数家族
浮点数类型在内存中的存储
一.为什么说整型和浮点数在内存中存储方式不同(证明)
二.浮点数的存储规则
浮点数在计算机内部的表示方法
1.对于M的存储和取出规则
2.对于E的存储和取出时的规则
对前面代码结果进行解释:
代码:
解释如图:
浮点数家族
包括 :float,double,long double
整型家族类型,表示的范围可以在 “limits.h”里查看
浮点数家族表示的范围在 “float.h” 中定义(可以在这里面查浮点数类型表示的精度,最大最小值等...)
以查看浮点数范围为例,打开float.h文件
如:
浮点数类型在内存中的存储
一.为什么说整型和浮点数在内存中存储方式不同(证明)
可以通过一个代码来解释整型和浮点数在内存中的存储方式是不同的
#define _CRT_SECURE_NO_WARNINGS 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;
}
运行结果:
运行结果分析:如果整型类型和浮点数类型的存储的方式一样,
预期结果应该是 9 9.00000 9 9.000000
所以通过这个结果可以看出整型和浮点型在内存中存储的方式有一定的差异
二.浮点数的存储规则
浮点数在计算机内部的表示方法
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式: (-1)^S * M * 2^E (-1)^S 表示符号位,当S=0,V为正数;当S=1,V为负数。 M表示有效数字,大于等于1,小于2。 2^E表示指数位。
举例来说: 十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。 那么,按照上面V的格式,可以得出S=0,M=1.01,E=2;
十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,S=1,M=1.01,E=2;
并且IEEE 754规定:
对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M。
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
特别注意的是对M和E的存储还有特别之处
1.对于M的存储和取出规则
首先,M的范围是1<=M<2的数,都可以写成1.xxxxxxx的形式,每个M小数点前面都有1,所以存出的时候只需要把小数点后面的xxxxxxx存储起来,取出的时候再统一在小数点前面加上1;这样的好处是:以32位 浮点数为例,留给M只有23位, 将第一位的1舍去以后,等于可以保存24位有效数字。
2.对于E的存储和取出时的规则
首先,E为一个无符号整数(unsigned int)
因为无符号整数只能表示正数,但是科学计数法中E是可以为负数,所以IEEE 754规定E在存入内存中时加上一个中间值,,对于8位的E,这个中间数 是127;对于11位的E,这个中间 数是1023。
比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即 10001001;又如2^-2的E是-2,所以保存成32位浮点数时,必须保存-2+127=125,即01111101,让E变为正数;
指数E从内存中取出还可以再分成三种情况:
1.不全为0和不全为1
E在存储时加了中间值 127 / 1023 ,所以E在取出时用减去 127 / 1023 ,得到真实值
0.5(1/2)的二进制形式为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.00000)
3.E全为1
即2^E,例:E为8位时,11111111转换为十进制为255,即2^255,是个很大的数了,更不用说11位的E了;所以,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);
对前面代码结果进行解释:
代码:
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;
}