数据存储(浮点型在内存中的存储)
Suzhou 14 0

常见的浮点数类型:float、double、long double。 ::: tip 浮点数的表示范围是在float.h中定义。整型类型的表示范围在limits.h中定义。 :::


浮点数在计算机内部的表示方法

数据存储(浮点型在内存中的存储) ::: tip 浮点型的二进制数需要小数点前和小数点后分别计算二进制序列步骤是浮点数计算成二进制序列,改写成科学计数法形式,加上符号位。 ::: 32位浮点数最高一位是符号位s,接着8位是指数E,剩下的23位是有效数字M。 数据存储(浮点型在内存中的存储) 64位浮点数最高一位是符号位s,接着11位是指数E,剩下的52位是有效数字M。 数据存储(浮点型在内存中的存储)

M和E的特殊规定

IEEE 754对于有效数字M的特殊规定: 对于任意一个数字,写成二进制数的形式时,都是1≤M≤2,将M写成1.xxxxxx,只保存小数部分的xxxxxx。即存储时将小数点前的1省略,取出时补上。当内存中的有效数字位都用来存储小数点后的数字时,精度高一位。

IEEE 754对于指数E的特殊规定: 在存储时E的8个或11个比特位中没有符号位,即E是无符号数(unsigned int)。单精度浮点数的E取值范围是0255,双精度浮点数的E取值范围是 02047。但科学计数法的E可以出现负数。 IEEE 754规定在存入内存时E的真实值(无论正负)需要加上中间数(用来转换成正数(无符号数)),对于8位的E,中间数是127;对于11位的E,中间数是1023。

例如:0.5的二进制表示是0.1,科学计数法表示是(-1)^01.02^-1,E为-1,存储进内存时,E+127变为126,此时E的真实值需要E-127得到。

int main()
{
    float a = 5.5;
    //5.5   - 十进制
    //101.1 - 二进制
    //(-1)^0*1.011*2^2 - 科学计数法
    //S = 0
    //M = 1.011
    //E = 2
    //E = 2 + 127 = 129 - 加上中间数存进内存
    //10000001 - E的二进制序列
    //0 10000001 01100000000000000000000 - 内存中由S、E、M组成
    //0100 0000 1011 0000 0000 0000 0000 0000
    //0x40b00000 - 改为16进制写法
    return 0;
}

数据存储(浮点型在内存中的存储)

E取出的三种情况
  • E不全为0或不全为1 常规情况。E减去127或1023还原为真实值。M前补上1和小数点。再组合成(-1)^0* M* 2^E。
  • E全为0 E加上127后的值为0,则E的真实值为-127。即±1.xxx* 2^-127,是一个非常接近于0的值。特殊规定如下:
  • 当浮点数的指数E等于1-127或1-1023时即为真实值。有效数字M前不再补1和小数点。此时数字为0.xxxxxx的小数,便于表示±0和接近于0的很小数字。* 组合后是±0.xxxxxx*2^-126。
  • E全为1 E加上127后的值为255,则E的真实值为128。即±1.xxxxxx*2^128,表示正负无穷大的值。

浮点数存储举例
int main()
{
    int n = 9;
    //00000000000000000000000000001001 - 补码
    float* pFloat = (float*)&n;
    printf("n的值是%d\n",n);
    //00000000000000000000000000001001   - 整型视角
    printf("*pFloat的值为%f\n",*pFloat);
    //0 00000000 00000000000000000001001 - 浮点型视角
    //E为全0时,M前补0和小数点,E取1-127,如下:
    //(-1)^0*0.00000000000000000001001*2^126
    //(%f输出float类型,输出6为小数)
    *pFloat = 9.0;
    //1001.0 - n的二进制序列
    //0*1.001*2^3 - 科学计数法
    //(-1)^0*1.001*2^3 - 存入内存中如下:
    //0 10000010 00100000000000000000000 - E = 3 + 127
    printf("num的值是%d\n", n);
    //01000001000100000000000000000000 - 整型视角
    //1091567616 - 符号位为,正数原反补相同,%d打印十进制数
    printf("*pFloat的值为%f\n", *pFloat);
    return 0;
}
n的值是9
*pFloat的值为0.000000
num的值是1091567616
*pFloat的值为9.000000

第6行代码以整形的形式存储,浮点型的形式取出,结果不是预想得到的。 第10行代码以浮点数的形式存储,整型的形式取出,结果不是预想得到的。 上述代码的结果可以看出内存中整型和浮点型存储的方式是不同的。 *pFloat解引用后一次可以访问4个字节。

::: tip 上述代码中n的类型是int,地址是int,赋给float类型的指针时进行强制类型转换。 *变量的地址的类型和变量的类型相同,如果需要赋给其他类型的指针,需要强制类型转换。**(如果没有精度丢失的情况,不会发生值的变化)。 :::

评论区

索引目录