Appearance
题目
已知 ,计算 的 C 语言函数 f1 如下:
c
int f1(unsigned n) {
int sum=1, power=1;
for(unsigned i=0; i<= n -1; i ++) {
power * = 2;
sum += power;
}
return sum ;
}将 f1 中的 int 都改为 float,可得到计算 f(n) 的另一个函数 f2。假设 unsigned 和 int 型数据都占 32 位,float 采用 IEEE754 单精度标准。请回答下列问题。
(1) 当 n=0 时,f1 会出现死循环,为什么?若将 f1 中的变量 i 和 n 都定义为 int 型,则 f1 是否还会出现死循环?为什么?
(2) f1(23) 和 f2(23) 的返回值是否相等?机器数各是什么(用十六进制表示)?
(3) f1(24) 和 f2(24) 的返回值分别为 33554431 和 33554432.0,为什么不相等?
(4) f(31)= 232−1 ,而 f1(31) 的返回值却为 -1,为什么?若使 f1(n) 的返回值与 f(n) 相等,则最大的 n 是多少?
(5) f2(127) 的机器数为 7F80 0000H,对应的值是什么?若使 f2(n) 的结果不溢出,则最大的 n 是多少?若使 f2(n) 的结果精确(无舍入),则最大的 n 是多少?
解析
本题用一个看似简单的求和函数 串起 5 个数据表示层面的考点:
- 无符号 vs 有符号:
n - 1在n = 0时的两种解读; - int vs float 表示能力:32 位 int 能精确到 ,而 float 只有 24 位有效尾数;
- IEEE 754 单精度:阶码偏置 127、阶码全 1 + 尾数 0 表示 ∞;
- 舍入:超过 24 位的尾数怎么进位、什么时候溢出。
(1) n=0 时 f1 死循环的原因 [4 分]
for (unsigned i = 0; i <= n-1; i++)。
unsigned 解读:
时,n - 1 在 unsigned 算术中按模 计算:
机器数为 32 个 1,值为 —— unsigned 能表示的最大数。判断条件 i <= n-1 永远成立(因为 i 是 unsigned,最大也才 )→ 死循环。
改成 int 后不会死循环。
n - 1 在 signed 补码算术下 = 。判断条件 i <= -1 在 i = 0 时即不成立 → for 循环一次都不进,直接退出。
易错点: "unsigned 减法溢出" 不会报错——它按模 安静地绕回最大值。这是 C 语言里"unsigned 不会负"的代价。如果要让
i <= n-1在n=0时也安全,常见写法是改成i < n。
(2) f1(23) 与 f2(23) 的返回值与机器数 [3 分]
,二进制 = 24 个 1。
返回值相等。 因为:
- int 32 位能容纳 ,24 位 1 没溢出;
- float 单精度有 23 位显式尾数 + 1 位隐含 = 24 位有效精度,恰好装下 24 位 1,无需舍入。
f1(23) 的机器数(int):
f2(23) 的机器数(float):
把 规格化:
- 符号位 S = 0;
- 阶码 E = ;
- 尾数 M =
1111 1111 1111 1111 1111 111(23 位,隐含的最高位 1 不存);
拼接:0 10010110 11111111111111111111111 → 分组:
(3) f1(24) 与 f2(24) 不等的原因 [2 分]
—— 25 个 1。
- int 能容纳 25 位 1( < )→ f1(24) = 33554431(精确);
- float 只有 24 位有效精度。
1111...1(25 位)规格化后尾数有 24 位(含隐含位),第 25 位被舍入。"舍入到偶"(IEEE 默认)下,最低位 1 被进位,结果 = = 33554432。
故 f2(24) 比 f1(24) 大 1。
易错点: float 不是"位数比 int 少"——float 32 位与 int 32 位长度相同,但 float 把 8 位用作阶码、23 位用作尾数,实际"精度"远小于 32 位。理解"动态范围 vs 精度"的取舍是浮点的关键。
【评分说明】只要说明 f2(24) 需舍入处理即可给分。
(4) f(31) 与 f1(31)、最大可精确 n [2 分]
为什么 f1(31) = -1?
,对应机器数 = 32 个 1 = FFFFFFFFH。在 32 位 int(补码)解释下:
f1 把 sum 当 int 返回,故得 −1。
最大 n 使 f1(n) = f(n):
要 不超过 int 最大值 :
【评分说明】只要给出 n=30 即可给分。
(5) f2(127) 的值、不溢出 / 精确的最大 n [3 分]
f2(127) = 7F800000H 对应的值。
按 IEEE 754 单精度拆解:
| 位段 | 值 | 含义 |
|---|---|---|
| S(1) | 0 | 正 |
| E(8) | 11111111 = 255 | 全 1 |
| M(23) | 0...0 | 全 0 |
阶码全 1、尾数全 0 → 表示 (IEEE 754 特殊编码)。
不溢出的最大 n:
f(n) ≈ ,规格化后阶码 = (先看尾数舍入)。单精度允许的最大有限阶码 = (即 E = 11111110)。
逐个验证:
- :,规格化 = (127 个 1)。24 位尾数容不下 127 个 1,舍入后尾数变成 ,阶码 +1 → 阶码 = 127,偏置后 E = 254,仍是有限数。不溢出。
- :,舍入后阶码 = 128,偏置 = 255 → 编码 = +∞。溢出。
故 不溢出的最大 n = 126。
精确(无舍入)的最大 n:
f(n) = 个 1。要不舍入,必须 → 。
编者注(生僻术语): IEEE 754 的"特殊值"包括:阶码全 0 + 尾数全 0 = ±0;阶码全 0 + 尾数非 0 = 非规格化数;阶码全 1 + 尾数全 0 = ±∞;阶码全 1 + 尾数非 0 = NaN。本题考的是 +∞ 这一情形。
【评分说明】只要给出 n=23(精确)和 n=126(不溢出)即可给分。