前言
本文内容
目录
浮点数在内存中的存储
一、浮点数类型
二、浮点数表示的范围
浮点数表示范围的定义在来自于 float.h 的定义
三、浮点数存储规则
1.浮点数二进制表示形式
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式
2.浮点数在内存中的存储方式
单精度浮点型
对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M。
双精度浮点型
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
3.IEEE 754的一些特别规定
IEEE 754对有效数字M和指数E,还有一些特别规定。
指数 M
前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的
xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。
以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。
指数E
E为一个无符号整数(unsigned int)
这意味着,如果E为8位,它的取值范围为0->255;如果E为11位,它的取值范围为0->2047。
但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。
比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即
10001001。
指数E从内存中取出的三种情况:
E不全为 0 或不全为 1
00111111000000000000000000000000SEM
E全为0
E全为1
四、实例讲解
1.实例代码
intmain() { intn=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); return0; }
2.输出结果
3.代码解析
错误案例
整形在内存中的存储方式分析
intmain() { intn=9; //整形 9float*pFloat= (float*)&n; //取出n的地址 再强转成float * 浮点数指针类型 printf("n的值为:%d\n",n); //假设 输出9printf("*pFloat的值为:%f\n",*pFloat); //假设 输出9.000000*pFloat=9.0; //解引用改变地址内的数据 从9——>9.0 printf("num的值为:%d\n",n); //假设 输出9printf("*pFloat的值为:%f\n",*pFloat); //假设 输出9.000000return0; }
证明
因为整形在内存的存储方式和浮点数在内存的存储方式不同,从而导致输出的结果于上面的假设输出存在差异。
n//假设输出 9 最终输出 9*pFloat(第一次)//假设输出 9.000000 最终输出 0.000000*pFloat=9.0; //解引用改变地址内的数据 从9——>9.0 num//假设输出 9 最终输出 1091567616*pFloat(第二次)//假设输出 9.000000 最终输出 9.000000
结果除了 n 和 *pFloat(第二次)输出跟假设的相同,从输出结果证明整形和浮点数在内存中的存储方式是不同的。
代码解析
intmain() { intn=9; float*pfloat= (float*)&n; //强制类型转换成float*类型printf("n的值为:%d\n", n); // n 本来是int类型 9 存入内存时 二进制表示 0000 0000 0000 0000 0000 0000 0000 1001//通过%d 形式输出 正数原反补相同 最终输出 9 ✔printf("*pfloat的值为:%f\n", *pfloat); //存入使是以整形类型存放的 9 二进制表示为 0000 0000 0000 0000 0000 0000 0000 1001 //当取出时以浮点数形式取出 //由于指数E全为0,所以符合上一节的第二种情况。//因此,浮点数V就写成://V = (-1) ^ 0 × 0.00000000000000000001001×2 ^ (-126) = 1.001×2 ^ (-146)//显然,V是一个很小的接近于0的正数,所以用十进制小数表示就是0.000000*pfloat=9.0; printf("num的值为:%d\n", n); //这里存入内存时是以float类型存入的 浮点数 9.0 -> 1001.0 -> 1.001*2^3//9.0 -> 1001.0 ->(-1)^01.0012^3 -> s=0, M=1.001,E=3+127=130//0 10000010 001 0000 0000 0000 0000 0000//整形输出 得1091567616printf("*pfloat的值为:%f\n", *pfloat); //存入和取出使都是浮点型 所以结果是9.000000return0; }
五、总结
六、完结