主要内容 #
本节,我们主要来探讨:小数在内存中是怎么表示的。
首先,和整数直接存储的方式不同。
小数是无法直接存储的,原因在于,整数有“单位一”,可以表示为多少个“一”。
然后,在内存中,可以相当于往柜子中放东西一样,将这个整数“逐一”放在内存空间中。
很显然,小数做不到这一点。
1. 科学计数法 #
在数学中,我们学习过:小数,一般也可以使用科学计数法来表示。
314159.26 = 3.1415926*10^5
使用科学计数法,一个小数可以用这样几个“整数”来表示。
314159.26 = 3.1415926*10^5 符号位 整数部分 小数部分 指数 0 3 1415926 5
类似的,由于我们在内存中的所有数值其实是二进制,
所以,我们需要先来了解“二进制中的科学计数法”
2. 二进制的科学计数法 #
先来计算 0.6 的二进制。
第一步 0.6*2=1.2 取1,得到 0.1 第二步 0.2*2=0.4 取0,得到 0.10 第三步 0.4*2=0.8 取0,得到 0.100 第四步 0.8*2=1.6 取1,得到 0.1001 第五步 0.6*2=1.2 取1,得到 0.10011 ... 从第五步开始循环 所以最终结果为:0.100110011001... 写作科学计数法:1.001100110011...*10^(-1) 符号位 整数部分 小数部分(保留一定的位数) 指数 0 1 001100110011 -1 二进制中,科学技术法的整数部分都是取 1 ,所以可以省略。最终结果为: 符号位 小数部分(保留一定的位数) 指数 0 001100110011 -1
所以,以 float 为例,小数在内存中的表示规则为:
符号位 小数部分(保留一定的位数) 指数 0 001100110011 -1 -1 加上127,得到 126:0111 1110 float 占 4 字节,32 位 0 |011 1111 0|001 1001 1001 1001 1001 1001 +- | 指数 | 小数部分 对应的十六进制为:0x3f19999a
3. 实验 #
请运行如下的代码,验证 0.6 的内存分布。
#include < iostream > using namespace std; int main() { float dashima = 0.6f; int* pa = (int*)(&dashima); // 转成等长度的整形,必须使用指针的强制类型转化 cout << setbase(16) << "0x"<< (*pa) << endl; // 3fc00000 return 0; }
4. 小结 #
符号位 阶码 尾数 总长度 float 1 8 23 32 double 1 11 52 64
习题 #