奎克的藏经阁 · 原书印刷页

编码 隐匿在计算机软硬件背后的语言 · 第 376 页

PDF 物理页索引 392 · 编码隐匿在计算机软硬件背后的语言

书名
编码 隐匿在计算机软硬件背后的语言
作者
未记录
印刷页
376
PDF 物理页
392(从 0 开始)
章节
编码隐匿在计算机软硬件背后的语言
UUID
38270854-596f-4a26-8183-db8c968c6020
来源类型
original_book
页面 SHA-256
6d5ef7c7026c75a50257dab892ae84d126b53d00a223426782782946762b3761

以同一个浮点数来表示两个不同的十进制数,有时可能成为一个问题,也可能不会。

但如果你为银行编写程序,用单精度浮点数来存放以美元、美分为单位的数字时,就会发现262144.00美元和262144.01美元在计算机中存储为同一个数:

$$
1 . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 _ { 2 } \times 2 ^ { 1 8 }
$$

这也是为什么人们在处理以美元、美分表示的钱款数目时更愿意使用定点数的一个原因。当使用浮点数时,你会发现它还存在着一些让人崩溃的小问题。你的程序进行了一系列计算,应该得到的结果为3.50的,但由于使用浮点数,你得到的可能是3.499999999999。这种问题在浮点数运算中经常发生,而且没有一套完整的解决方案。

如果想在程序中使用浮点格式数,但使用单精度格式又会出现各种问题,这时你可以考虑使用双精度浮点数(double-precision floating-point format)。这种类型的数需要用8个字节来表示,它的结构如下表所示。

双精度浮点数的指数偏移量是1023,或十六进制的3FFh,因此以该格式存储的数可以表示为:

$$
( - 1 ) ^ { s } \times 1 . f \times 2 ^ { e - 1 0 2 3 }
$$

上面提到的关于单精度浮点格式下的0,无穷大(小)和NaN的判断规则同样适用于双精度浮点格式。

双精度浮点格式下可以表示的最小正数或负数为:

$$
1 . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
$$

注意,小数点的后面共有52个 $\mathbf { 0 } _ { \circ }$ 同样的,可以表示的最大数为:

$$
1 . 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
$$

其所能表示的范围,用十进制可以近似记为:

$$
2 . 2 2 5 0 7 3 8 5 8 5 0 7 2 0 1 4 \times 1 0 ^ { - 3 0 8 } \mathrm { { \sim } } 1 . 7 9 7 6 9 3 1 3 4 8 6 2 3 1 5 8 \times 1 0 ^ { 3 0 8 }
$$

10的308次幂是一个非常巨大的数,在1的后面跟着308个0。

编码隐匿在计算机软硬件背后的语言

376