Appearance
题目
假定变量 i、f 和 d 的数据类型分别为 int、float 和 double(int 用补码表示,float 和 double 分别用 IEEE 754 单精度和双精度浮点数格式表示),已知 i=785,f=1.5678e3,d=1.5e100。若在 32 位机器中执行下列关系表达式,则结果为"真"的是( )。
I. i == (int)(float)i
II. f == (float)(int)f
III. f == (float)(double)f
IV. (d+f)-d == f
错因
A
I 选对,但把 II 也判成"真"——可能默认"(int)f 再 (float) 回来还是 f",忽略了强转 int 时小数部分会被截断。f = 1567.8,先取整变 1567,再转回 float 是 1567.0,与原 f 差 0.8。这是类型转换里最常见的"信息丢了就回不来"。
C
II 误判为真(同 A 的错),III 选对。把 II 当真的核心心理错觉:忽略 (int) 的截断动作。
D
把 III 选对了(合理),但误把 IV 也判成真——这是这题最大的陷阱。直觉认为 "(d+f)-d" 在数学上当然等于 f,可是浮点加法不是数学加法:d = 1.5×10¹⁰⁰ 比 f ≈ 1568 大约 100 个数量级,两者相加时为了对阶,f 的尾数要右移近 332 位(远超 double 的 52 位尾数),整个 f 被吞掉,d+f 在浮点表示里就等于 d,于是 (d+f)-d = 0 ≠ f。这是计算机数值分析里经典的"大数吃小数"。
总解析
核心规则速记:
- float(单精度):23 位尾数 + 1 位隐含位 = 24 位有效位,能精确表示约 之内的整数
- double(双精度):52 位尾数 + 1 位隐含位 = 53 位有效位
- 浮点加法对阶时,指数差大于尾数位数的小数会被完全舍掉(俗称"大数吃小数")
逐项分析:
I. i == (int)(float)i,i = 785
785 < → 在 float 精确表示范围内,无损 round-trip。
等式 真 ✓
II. f == (float)(int)f,f = 1.5678×10³ = 1567.8
(int) 是截断(向 0 取整),不是四舍五入:
等式 假 ✗(小数部分 0.8 永久丢失)
III. f == (float)(double)f,f 是 float
float 升 double 无损(double 表示范围更大、精度更高,原始 float 的位串可以精确重现);double 降回 float 时,因为该 double 值刚好是某个 float 的值,精确还原。
等式 真 ✓
IV. (d+f)-d == f,d = 1.5×10¹⁰⁰,f ≈ 1.5678×10³
d 与 f 量级差约 → 对应二进制指数差约 位,远超 double 的 52 位尾数。
d + f:对阶后 f 被右移 322 位,全部位移出,相加后结果就是 d(d + f) - d= d − d = 0- 0 ≠ f
等式 假 ✗
汇总:
| 表达式 | 真假 | 原因 |
|---|---|---|
| I | 真 | 785 在 float 精度内 |
| II | 假 | (int) 截断小数 |
| III | 真 | float→double→float 无损 |
| IV | 假 | 大数吃小数(d 吃掉 f) |
最终答案是 B(仅 I 和 III)。
记忆口诀:
- "升精度无损、降精度可能丢" —— III 的逻辑
- "float ↔ int 转换看是否截断 + 数值是否在 24 位整数精度内" —— I 真 II 假的分水岭
- "数量级悬殊的浮点加减,小的会被吃掉" —— IV 的陷阱本质