尝试表示 2^(-23) 时在单精度 IEEE-754 中难以掌握 "error due to conversion"
Trouble grasping "error due to conversion" in single-precision IEEE-754 when attempting to represent 2^(-23)
让我先说明问题,我明白为什么 0.1
、3.14
、0.2
等值以及其他不能由两个幂的组合组合的值最终是无法用 IEEE-754 格式表示,并且它们只能在精度允许的情况下尽可能接近。
我无法理解的是为什么尝试表示值 2-23 会导致轻微的误差。
2-23正好等于1.1920928955078e-7
,或者0.00000011920928955078
。
在单精度IEEE-754中,可以这样构造:
- 符号位为
0
- 偏置指数为
104
(或二进制 0b01101000
)以解释 127 偏置,导致 -23
成为最终指数值
- 尾数的位域全部由
0
组成,算上隐含的1
位后最终值为1.0
但是,将这个特定的位序列存储在内存中并以十进制表示法打印出来,小数点后有 25 位精度,结果如下:
0.0000001192092895507812500
^
|
margin of error starts here
这个值恰好包含 1.25e-21
的错误。在 this interactive website 上,此错误值称为“由于转换引起的错误”。
我很难理解这一点——因为我明白,例如,为什么像 +3.14
这样的值不能用单精度位域精确表示。由指数中的值缩放的尾数中两个负幂的组合不能 精确地 表示 3.14
,因此选择下一个最接近的近似值。因此,预计会出现“由于转换而导致的错误”。与此相反,值 2-23 可以 exactly 存储在单精度中位域,但当转换回十进制表示法时,出现错误。
我显然有某种误解,但我想不通到底在哪里。
2-23其实是不是 正好等于 1.1920928955078e-7
.
我用来执行计算的软件截断了结果
短三位数... 2-23的精确值正好是0.00000011920928955078125
,或者1.1920928955078125e-7
,也就是我之前观察到的输出,使其正确无误。
同样值得一提的是,该网站将尾数的十进制表示提前截断了几位,进行手工计算(即尾数乘以符号位和2指数) 看起来不正确(或至少略有偏差),但实际上不正确。
让我先说明问题,我明白为什么 0.1
、3.14
、0.2
等值以及其他不能由两个幂的组合组合的值最终是无法用 IEEE-754 格式表示,并且它们只能在精度允许的情况下尽可能接近。
我无法理解的是为什么尝试表示值 2-23 会导致轻微的误差。
2-23正好等于1.1920928955078e-7
,或者0.00000011920928955078
。
在单精度IEEE-754中,可以这样构造:
- 符号位为
0
- 偏置指数为
104
(或二进制0b01101000
)以解释 127 偏置,导致-23
成为最终指数值 - 尾数的位域全部由
0
组成,算上隐含的1
位后最终值为1.0
但是,将这个特定的位序列存储在内存中并以十进制表示法打印出来,小数点后有 25 位精度,结果如下:
0.0000001192092895507812500
^
|
margin of error starts here
这个值恰好包含 1.25e-21
的错误。在 this interactive website 上,此错误值称为“由于转换引起的错误”。
我很难理解这一点——因为我明白,例如,为什么像 +3.14
这样的值不能用单精度位域精确表示。由指数中的值缩放的尾数中两个负幂的组合不能 精确地 表示 3.14
,因此选择下一个最接近的近似值。因此,预计会出现“由于转换而导致的错误”。与此相反,值 2-23 可以 exactly 存储在单精度中位域,但当转换回十进制表示法时,出现错误。
我显然有某种误解,但我想不通到底在哪里。
2-23其实是不是 正好等于 1.1920928955078e-7
.
我用来执行计算的软件截断了结果
短三位数... 2-23的精确值正好是0.00000011920928955078125
,或者1.1920928955078125e-7
,也就是我之前观察到的输出,使其正确无误。
同样值得一提的是,该网站将尾数的十进制表示提前截断了几位,进行手工计算(即尾数乘以符号位和2指数) 看起来不正确(或至少略有偏差),但实际上不正确。