前言:
数学当中的小数相信大家不会陌生,它就是浮点数,而在我们C语言当中什么是浮点数,浮点数又有哪些类型呢,它在内存当中又是如何存储的呢,笼统的来说带小数的都是浮点数,它的类型有float,double,long double等等,那么关键的来了,它在内存中是如何存储的呢,整数在内存当中存储的是二进制以0/1来表示一个整数的大小,那么浮点数是和整数以相同方式存储的吗,下边我们来一一为兄弟们解答
下边我们来看一组代码,相信大家会有更加直观的感觉:
int main()
{
float a = 5.25f;
int b = 10;
float* p = (float*)&b;
printf("a的值为:%.2f\n", a);
printf("b的值为:%d\n", b);
printf("*p的值为:%.2f\n", *p);
}
上述代码中如果浮点数和整数是按照同一种方式存储的话,那么它的执行结果应为:
a = 5.25 b = 10 *p = 5.25
但是结果真是如此吗,我们代码执行结果看一下:
很显然*p的值完全不一样,所以可以得出浮点数在内存当中存储与整数存储是完全不一样的
根据国际标准IEEE(电⽓和电⼦⼯程协会)754,任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:
由于该形式是已经规定好了的,所以在存储时我们只要确定好S,M,E这三个变量即可算出正确的浮点值,同理C语言在存储浮点数时也只需要存储这些变量
拿32位操作系统举例,最高位存储符号位S为1个字节,指数E为8个字节(255),剩下的23位全部归于M:
同理,64位操作系统,最高位存储符号位S为1个字节,指数E为11个字节(1027),剩下的52位全部归于M
现在我们理解了这三个变量的含义,那么它们在内存当中又是如何存放的呢,根据IEEE754规定:
S为数字的符号位,为0该数为正数,为1该数为负数,而M的话由于它恒是一个1<M<2的数,所以在存储时,总是以1.xxxxx存储,这个1是一直保持不变的,此时,内存中就会将这个1省略,后续从内存取出时,再给它补上,比如,M=1.011,此时内存中存储时M会被存储为.011,这样存储后,该数会少占用一个字节位,在32位操作系统中,则M的有效位会达到23+1位
指数E为无符号整数,在内存当中存储的是非负数,这个时候问题来了,如果它得出来的结果为负数又改怎么办呢,为了避免这一现象的产生,IEEE745规定,指数E在存储时会在原来数的基础上+127保证该数>=0,比如当E=2时,内存存储的是2+127的二进制,下边咱来看一组数据给兄弟们加深一下印象
举例:
则:-1^0*(1.0101)*2^2 = 101.01,十进制最后得出5.25
举例:
int main()
{
int a = 10;
float* p = (float*) &a;
printf("*p的值:%f\n", *p);
*p = 15.0;
printf("*p的值:%f", *p);
//10的二进制为: 0 00000000 00000000000000000001010
//因为浮点数在内存中是按照 (-1)^S*M*2^E
//此时S=0,M=1.01,E=2 根据IEEE754规定,所以最终在内存中存储的数据为
// 由于指数E为全0,所以M中补0
//S=0,E=00000000,M=00000000000000000001010
//(-1)^0*0.00000000000000000001010*2^(-126)
//此时这个数无限接近于0,float类型在这个时候精度不够,所以最后输出0.0000000
//第二个*p
//由于后边赋值的类型是浮点型,所以找原样输出,15.000000
}
执行结果:
(今日分享到此结束,如有高见,欢迎评论区留言,Thanks♪(・ω・)ノ!!!)