IEEE 754 float浮点数浅析

IEEE 754标准出现之前,业界对机器浮点数表示各有一套说法,这就造成了浮点代码在机器间的移植性表现极差。IEEE规定了通用机器浮点数标准,今天几乎所有计算机都支持IEEE 754,且默认使用的浮点数标准就是IEEE 754。关于浮点数应具备的基本常识,课本上讲的也稍微枯燥,自己理解起来不容易。希望此篇通俗易懂的简要介绍,能使你对IEEE 754浮点数知识体系有深刻的认识。

一、为什么使用浮点数?

浮点数的概念是相对于定点数而出现的。定点数是指小数点固定的数,包括无符号整数,有符号整数,定点小数。举几个例子:

无符号整数: unsigned int a = 23
有符号整数: long long a = 3294294899455
定点小数: 在数据位宽为5位时,01101表示+0.1101,若符号位为1则为负

浮点数就是小数点是逻辑上浮动的数。既然定点数用起来非常简单,且运算速度极快,那为什么还要使用浮点数呢?考虑以下的情况:

现欲表示5 * 2 100,写成二进制计数就是:1.01 * 2 102
如果是定点表示,那么要表示成:
在这里插入图片描述
这105个bits,都要老老实实地在内存中存储,未免太浪费空间,不切实际。因此,借鉴科学计数法的思想,我们不是只要把 X * 2 Y 中的X和Y表示一下,就可以了吗?在我们这个例子中,X就是101(B),Y就是102(D)

上述的改进思想其实就是IEEE 754的核心方法。

二、IEEE 754 浮点数的4种表示格式

均以float为例,double自己类推就好。

以下记符号位为 s,指数位为 e,尾数位为 f

规格化

在这里插入图片描述
它表示的数是:(-1)s * 1.f * 2 e

注意在IEEE 754浮点标准中,指数位都是移码表示,对float而言,也就是:

实际指数 = 位表示的指数 - 127

也就是说,如果现在指数位为0111 1111,则实际指数应该为0111 1111的十进制表示127减去127,也就是0;反过来,如果现在要表示的是0次幂,则应该表示为0111 1111

以5为例,其表示为:

在这里插入图片描述
其中,第1位为0,说明它是一个非负数;[2,9]为1000 0001(129),减去127得到实际指数为2,尾数位为1.01,则表示的就是 5 = 1.01 * 2 2

  • 最小的规格化数为:0 00000001 00000000000000000000000
  • 最大的规格化数为:0 11111110 11111111111111111111111
非规格化

在这里插入图片描述
非规格化表示中,指数位全为0

它表示的数是:(-1)s * 0.f * 2 -126

  • 最小的非规格化数为:0 00000000 00000000000000000000001
  • 最大的非规格化数为:0 00000000 11111111111111111111111
无穷大

在这里插入图片描述
例如:double(7) / double(0) 的结果为

在这里插入图片描述

非数

在这里插入图片描述
例如:sqrt(-1)的结果为

在这里插入图片描述

三、关于舍入

舍入,实际上就是在原有四舍五入的基础上加以修改。例如,0.49还是舍入到0,0.51还是舍入到1,关键在于0.5的舍入。一般采用向偶数舍入(也叫向最接近的值舍入),这样一来,对于位居中央的数,就向偶数舍入。例如,1.5舍入到2,2.5舍入到2,3.5舍入到4…向偶数舍入可以理解为:最后一位表示为 0

23位实在太长有点难以距离,我们假设现在有一个玩具模型,有1位符号位,4位指数位和4位尾数位。那么:

33 = 1.00001 * 2 5,假设现在尾数位数足够的话,那么33应该被表示成0 1100 00001,但是现在由于尾数只有4位可以存储,所以会发生截断舍入,舍入的结果(要让尾数的第 4 位为偶数)为0 1100 0000

35 = 1.00011 * 2 5,假设现在尾数位数足够的话,那么35应该被表示成0 1100 00011,但是现在由于尾数只有4位可以存储,所以会发生截断舍入,舍入的结果(要让尾数的第 4 位为偶数)为0 1100 0010

四、如何查看浮点数的位表示?

写一段C++代码就可以解决了:

考虑因素:

  • Windows是小端法机器
# include <iostream>
# include <bitset>
# include <math.h>
using namespace std;

typedef unsigned char* ptr;

int main() {
    float a;
    cin >> a;
    ptr st = ptr(&a);
    for (int i = 3; i >= 0; --i) {
        bitset<8> bs(st[i]);
        for (int j = 7; j >= 0; --j) {
            cout << bs[j];
        }
        cout << " ";
    }
    cout << endl;
    return 0;
}

  • 10
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值