C++旧版课程库
C++第 3 期查看课程总览

077 内存中的浮点数

主要内容

本节,我们主要来探讨:小数在内存中是怎么表示的。 首先,和整数直接存储的方式不同。 小数是无法直接存储的,原因在于,整数有“单位一”,可以表示为多少个“一”。 然后,在内存中,可以相当于往柜子中放东西一样,将这个整数“逐一”放在内存空间中。 很显然,小数做不到这一点。

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 为例,小数在内存中的表示规则为:
  • 第 1 位是符号位,1 表示负数,0表示非负数
  • 第 2~9 位(共8位),是“指数”,也称为“阶码”
  • “指数”,把真值+127
  • 第 10~32 位(共23位),是“小数部分”,也称为“尾数”
  • “小数部分”,近似方法:用0舍1
  • 
    符号位    小数部分(保留一定的位数)    指数
    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
    

    习题

    课后练习