Skip to content

标题

CS-MEDIUM-02 浮点数

说明

本题目旨在帮助大家理解浮点数在计算机中的表示原理,推荐阅读《深入理解计算机系统》(CSAPP) 第 2.4 节 "浮点数"

Step 1.认识浮点数

请编写并运行如下代码,观察输出结果:

c
#include <stdio.h>
int main() {
    float a = 0.1;
    printf("%.20f\n", a);
    return 0;
}
#include <stdio.h>
int main() {
    float a = 0.1;
    printf("%.20f\n", a);
    return 0;
}

在数学上,0.1 就是 0.100000...,所以你可能预期会输出 0.10000000000000000000

但实际运行,你却会看到一个略微不同的值。

首先我们知道计算机底层使用二进制表示所有数据,包括浮点数。但并不是所有的十进制小数都能被二进制精确表示。

所以你能解释为什么 0.1 并没有被精确表示出来吗?

误差的根本原因,还与浮点数的存储结构有关。根据 IEEE 754 浮点数标准,一个浮点数由三部分构成:

符号位(sign):1 位,决定正负。

阶码(exponent):表示数量级,类似科学计数法中的指数部分。

尾数(significand):表示有效数字部分。

例如,1.234×105-1.234 \times 10^5 在浮点存储中会被拆分成:

  • 符号位:1(负数)
  • 阶码:5(会加偏置存储)
  • 尾数:1.234(存储时去掉首位 1 只保留小数部分)

请查阅相关资料并回答:

IEEE 754 标准中,float 与 double 分别使用多少位来表示这三部分?

在存储阶码时,IEEE 754 并不直接保存正负值,而是把它加上一个**偏置(Bias)**后存为无符号整数。

例如:在一个float类型中,若阶码实际值为5,但在计算机中存储的却是:5+127=1335+127 = 133

请回答:偏置值是如何计算的?这样做的意义是什么?

当浮点数表示的数值非常接近 0 时,规格化表示的阶码已经到最小了,不能再减。这时会用非规格化数

请查阅相关资料并回答:

非规格化数的特点是什么?

此外,还有两个特殊阶码模式:

  1. 阶码全为 1 且尾数全为 0
  2. 阶码全为 1 且尾数非 0

回答这两个特殊阶码模式分别指的什么?

注意:该任务仅为导读,要学习浮点数请阅读相关书籍或观看相关视频。

要求:在markdown中回答上述中出现的问题

Step 2.表示浮点数

假设一个基于IEEE浮点格式的8位浮点表示,有1个符号位、 4个阶码位(k=4)和3个小数位(n=3)。阶码偏置值是2411=72^{4-1}-1 = 7。下表中列举了这个8位浮点表示的部分非负取值。使用下面的条件,填写表格中的空白项:

e: 假定阶码字段是一个无符号整数所表示的值。

E: 偏置之后的阶码值。

2E2^E: 阶码的权重。

f: 小数值。

M: 尾数的值。

2E×M2^E \times M: 该数小数值(无需化为最简)。

十进制:该数的十进制表示(不超过六位小数)。

注意:2E2^E、f、M、2E×M2^E \times M的值,要么是整数(如果可能的话),要么是形如xy\frac{x}{y}的小数,这里y是2的幂。标注为“—”的条目不用填。

位表示eE2E2^EfM2E×M2^E \times M十进制
0 0000 0000-6164\frac{1}{64}08\frac{0}{8}08\frac{0}{8}0512\frac{0}{512}0.0
0 0000 001
0 0000 011
0 0000 111
0 0001 0001-6164\frac{1}{64}08\frac{0}{8}88\frac{8}{8}8512\frac{8}{512}0.015625
0 0001 001
0 0111 000
0 0111 110
0 1110 111
0 1111 000

思考:

  • 在该8位浮点表示中,最小的非规格化数、最大的非规格化数、最小的规格化数、最大的规格化数、无穷大的位表示分别是什么?
  • 对于非规格化形式,阶码值为什么是1Bias1 - Bias而不是简单的Bias-Bias

提交方式:于markdown中提交完整的表格,并回答思考题。

Step 3

要求:仿照IEEE 754 标准,实现一个C程序,要求输入5位浮点字符串,输出对应的十进制值。

其中5位浮点数格式如下:

  • 符号位:0表示正数,1表示负数
  • 阶码:2位
  • 尾数:2位
  • 偏置值2211=12^{2-1}-1 = 1

输入输出示例:

输入输出
000000
000100.5
10101-1.25
01100+Inf
01111NaN

提交方式:markdown中提交相关代码和运行截图。

Step 4.浮点数的简单运算

相信在完成上述任务之后你对浮点数已经有了比较深刻的认识,现在让我们来看看浮点数的加减法是如何实现的。

浮点数的加减运算一般由以下五个步骤完成:对阶尾数运算规格化舍入处理溢出判断

1.对阶

所谓对阶是指将两个进行运算的浮点数的阶码对齐的操作。类比平常我们用到的带阶数的加减法,对阶的目的是为使两个浮点数的尾数能够进行加减运算。在对阶的过程中有两种方式,大阶向小阶看齐,小阶向大阶看齐。但实际上我们是用小阶向大阶看齐的方式。请思考其中的原因。

2.尾数运算

尾数运算就是进行完成对阶后的尾数相加减。

3.规格化

对于IEEE754标准的浮点数来说,由于在进行上述两个定点小数的尾数相加减运算后,尾数有可能是非规格化形式,为此必须进行规格化操作。规格化操作包括左规和右规两种情况。

左规操作将尾数左移,同时阶码减值,直至尾数成为1.M的形式。例如,浮点数0.001111是非规格化的形式,需进行左规操作,将其尾数左移3位,同时阶码减3,就变成1.110000规格化形式了。

右规操作将尾数右移1位,同时阶码增1,便成为规格化的形式了。要注意的是,右规操作只需将尾数右移一位即可,这种情况出现在尾数的最高位(小数点前一位)运算时出现了进位,使尾数成为10.xxxx或11.xxxx的形式。例如,10.001100右规一位后便成为1.0001100的规格化形式了。

4.舍入处理

浮点运算在对阶或右规时,尾数需要右移,被右移出去的位会被丢掉,从而造成运算结果精度的损失。为了减少这种精度损失,可以将一定位数的移出位先保留起来,称为保护位,在规格化后用于舍入处理。IEEE754标准列出了四种可选的舍入处理方法,这里请自行查阅不详细列出。

5.溢出判断

与定点数运算不同的是,浮点数的溢出是以其运算结果的阶码的值是否产生溢出来判断的。若阶码的值超过了阶码所能表示的最大正数,则为上溢,进一步,若此时浮点数为正数,则为正上溢,记为+∞,若浮点数为负数,则为负上溢,记为-∞;若阶码的值超过了阶码所能表示的最小负数,则为下溢,进一步,若此时浮点数为正数,则为正下溢,若浮点数为负数,则为负下溢。正下溢和负下溢都作为0处理。

下面给出具体运算过程示例(以32位系统为例):

float a = 0.3; b = 1.6;

a = 0011 1110 1001 1001 1001 1001 1001 1010 Sa=0 Ea=011 1110 1 Ma=1.001 1001 1001 1001 1001 1010

b = 0011 1111 1100 1100 1100 1100 1100 1101 Sb=0 Eb=011 1111 1 Mb=1.100 1100 1100 1100 1100 1101

a + b= ?

第一步:对阶

∵ Ea < Eb Eb - Ea = 2

∴ Ma要调整为 0.0 1001 1001 1001 1001 1001 10 10

E = 011 1111 1

第二步:尾数运算

0.01001100110011001100110

+1.10011001100110011001101

1.11100110011001100110011

第三步:规格化

1.11100110011001100110011已经是个规格化数据了

第四步:舍入处理

由于在对阶时,Ma有右移,且第一次最高为1,第二次为0,所以按"0舍1入",尾数运算结果调整为 1.11100110011001100110100

第五步:溢出判断

没有溢出,阶码不调整,所以最后的结果为

a+b = 0 01111111 11100110011001100110100 = 0011 1111 1111 0011 0011 0011 0011 0100

转为10进制

a+b = 1.90000010

按照任务二的八位浮点系统,请设计一个c程序,要求为输入两个八位二进制浮点数(中间用空格隔开),然后对两个浮点数进行加法操作,只完成对阶尾数运算规格化的操作,输出规格化后的二进制表达式(不考虑溢出,若需进行舍入采取向零舍入)。为简化实现,本题只考虑非负的规格化数,忽略非规格化数和其它特殊情况

输入输出示例

输入输出
01001011 0100110001010011
01000110 0100110101010010
01001000 0100011101001111
01000111 0100010101001110

提交方式:markdown中提交相关代码和运行截图。

本题提交方式

提交点这里

出题人联系方式

逐影 QQ:1329007256