frendguo's blog

计算机中浮点数的表示法

1.

今天看C++的面试题,看到这样的一道题:

#include <iostream>

using namespace std;

int main(void)
{
    float a = 1.0;
    cout << (int)a << endl;
    cout << (int &)a << endl;
    cout << boolalpha << ( (int)a == (int &)a) << endl;

    float b = 0;
    cout << (int)b << endl;
    cout << (int &)b << endl;
    cout << boolalpha << ( (int)b == (int &)b ) << endl;
    return 0;
}

刚开始其实是不知道这道题的考点是什么的,然后运行了一样。得到这样的结果:

2.

这里主要牵涉到浮点数在计算机内部的存放。在讨论浮点数之前,先讨论下整数在计算机内部的存放方式。

int num = 4;

上面这条语句声明了一个有符号整形(int)变量 num ,并初始化成 4 (二进制表示为:100),所以在计算机中表示为:00000000 00000000 00000000 00000100 

那浮点数改怎么在计算机内部表示呢?别着急,我们娓娓道来

根据IEEE 754 标准,浮点数在计算机内部是这样表示的:看这里》》

3.

接下来就对着上面这幅图来好好说下浮点数在计算机内部的构成:

  • S :表示符号位,很容易看出  0=》正数1 =》负数 
  • Exponent:也就是指数了。但它又不是实际上的指数。为什么这么说呢?因为在我们的科学计数法中指数(E)是可以表示成负数的。所以IEEE 754就规定:E 的值表示为 真实的指数值 + 偏移值(单精度是127,双精度是1023);换句话来说就是,我们真实的指数应该是计算机内部相应位的值再减去偏移值之后得到的值。说起来可能还是有点不清不楚的,待会看实例就好了。
  • Fraction:表示小数部分。对于小数部分我们需要注意的就是 该值应该是属于 [1.0, 2.0)  ,因为该值整数部分都是 1 ,所以在计算机内部是不会存储该值的整数部分的(假设Fraction 表示成:1.xxxxxx 的形式,实际的存储中,Fraction 应该就是 xxxxxx 了)。正如上图所示,要计算计算计算机中存储的浮点数的值时,应该将 Fraction 的值加上 1.

4.

这里我们举几个例子再来理解下浮点数在计算机内部的存储。(以单精度为例)

float n = 1.0;

n 在计算机中的存储应该是怎样的呢?我们首先将 n 用科学计数法表示:n = (-1) ^ 0 * 1.0 * 2 ^ 0

 

所以 S = 0; Exponent = 1.0 - 1 = 0;Fraction = 0 + 127 = 0111 1111;

于是 n 在计算机内部的表示应该是: 00111111 10000000 00000000 00000000

好的 我们验证下:

float n2 = 12.55

这里首先将十进制转化成二进制(怎么转化?自行百度。。总结起来其实就是整数部分 除 k 取余,小数部分乘 k 取整 )n2 = 1100.10001100110011001101

然后将 n2 的二进制用科学计数法表示出来:n2 = (-1) ^ 0 * 1.10010001100110011001101 * 2 ^ 3;

所以 S = 0;Exponent = 1.10010001100110011001101 -  1 =  10010001100110011001101;Fraction = 3 + 127 = 10000010;

于是就得到了 n2 在计算机内部的表示应该是:01000001 01001000 11001100 11001101

验证下:

5.

如果有仔细看看这里》》,一定会看到这个:

于是根据这个我们知道全 0 和全 1 都是属于保留情况,不属于正常规则范围内,我们也来讨论下Exponent 的取值(仍然以单精度浮点数为例):

  1. 介于 00000000 和 11111111 之间:这时就是正常情况,按照上面讨论的规则来表示浮点数。
  2. 全是 0 的情况:这时对于 Fraction 部分就不需要加 1 了。而是还原为 0.xxxxxx 的小数。这么做是为了表示±0,以及接近于0的很小的数字。
  3. 全是 1 的情况:这中情况下,就得看 Fraction 部分了,如果 Fraction 部分全是 1 ,则表示该数是无穷大的,而如果 Fraction 部分不全是 1 ,则表示该数不是数字(NAN)。

Happy Coding!o(* ̄▽ ̄*)o

 

Add comment

Loading