欢迎使用CSDN-markdown编辑器

来源:互联网 发布:tim linux 编辑:程序博客网 时间:2024/06/17 19:39

本文转载自我的个人微博

http://www.zibuyu.me//%E5%B7%A5%E5%85%B7/2017/03/22/Float-Max-Value.html

这是 2012年 计算机研究生专业课考试里的一道选择题.

这道题考察 “计算机组成原理” 这门课程中的内容.

首先理解 IEEE 754 中, 是怎样表示浮点数的

在此标准中, float 32 位, double 64 位.

实数 8.25 的二进制表示: 1000.01 -> 1.00001 * 2 ^3. 下面以此数为例, 按位解析其浮点数表示.

第一位: 符号位. 0 表示正数, 1表示负数. 8.25 为正数对应此位为0.

第二位 - 第九位: 指数位, 表示 2 的多少次方.

这里细节比较多, 以 float 举例:

首先看表示范围. 8位, 同时表示正负数, 按标准正数最大 128, 负数最小 -127 (是的, 不是127 ~ -128, 和大多数编程语言定义数值范围不一样). 但全0用来表示0值, 全1用来表示无穷大或 NaN (not a number, 具体表示什么还要参照数值位, 数值位全为0表示无穷大, 非0表示NaN). 既然0和1都被占用, 所以指数位能够表示的范围变成 127 ~ -126.

然后看指数偏移量: 为了避免有正有负加大复杂度, 对上面这个范围内的数, 统一加上一个偏移量 – 127 (double 为 1023), 注意全0被占用了, 所以 -126 + 127 = 1, 刚刚好. 这样用无符号正数来表示指数位, 但它实际表示的值依然是原来的范围 127 ~ -126.

8.25 的指数位为 2^3, 数值为3, 加上指数偏移量, 实际存储形式为 127 + 3 = 130 -> 10000010

剩余的31位: 数值位. 注意我们把 8.25 表示为2进制指数后, 小数点前面是保留了一个1的, 这是规范要求. 在实际存储中, 这个固定保留的1会被省略, 也就是仅存储 0.00001.

所以, 最终内存中保存的实际二进制值为:

符号位: 0

指数位: 10000010

数值位: 00001

相加后:

0 10000010 00001000000000000000000

再来看最大值

经过上面的分析, 我们应该明确, 所谓浮点数的最大值, 在内存中的表示应该是:

0 11111110 11111111111111111111111

符号位为0, 正数

指数位为11111110, 减去指数偏移量127后, 对应的实际指数应该为 2^127

再来看数值位的一堆1, 他们代表 0.1111…111, 按标准, 我们把之前省略的小数点前面的一个1加回来, 变成 1.111…111, 这是二进制表示, 我们考虑变成十进制表示.

可以这样转换: 1 + 1 - 0.000…001, 这一步要弄懂, 1.112…111 + 0.000…001 后, 就变成 1 + 1 了, 所以 1.111…111 = 1 + 1 - 0.000…001.

再回忆二进制小数和十进制的转换规则. (0.1)b = 2^-1, (0.01)b = 2^-2, 所以这里的(0.000…001)b = 2^-23.

所以最终这个最大值变成十进制表示, 就为 (1+1-2^-23) * 2^127 , 最终这个式子就可以换算出前面考研试题中的结果: D

0 0