计算机中的浮点数

写这篇blog,是因为在上工程硕士数学时候,又开始讲到了浮点数的储存,运算和精度的问题。这个问题已经见了好多次了,从微机原理的课到计算机视觉处理矩阵时候的conditioning,到这次。但感觉一直都没有理清楚。所以这次尝试梳理一下。

数在计算机中的存储

一般主要分为两种形式,这里以8位的存储进行解释:

  • 定点数
    定点数,很直观地理解就是小数点是固定的,如 b 0 b 1 . b 2 b 3 b 4 b 5 b 6 b 7 b_0b_1.b_2b_3b_4b_5b_6b_7 b0b1.b2b3b4b5b6b7,就是固定整数部分是两位,小数部分是六位的情况。在这种情况下,表示范围和精度都固定下来了。
    表 示 范 围 : x = 0 ∼ 2 2 − 2 − 6 精 度 : Δ x m i n = 2 − 6 十 进 制 转 换 : x 10 = ∑ i b i ∗ 2 i , b i = 0 o r 1 表示范围:x = 0 \sim 2^2-2^{-6}\\ 精度:\Delta x_{min} = 2^{-6}\\ 十进制转换: x_{10} = \sum_i{b_i*2^i}, b_i = 0 or 1 x=02226Δxmin=26x10=ibi2i,bi=0or1
  • 浮点数
    浮点浮点,就是小数点是可以浮动的呗。因此需要一定的规范去约束大家的定义,一般采取IEEE-754标准。下图为单精度浮点数。其中,第一段s为符号位,第二段为指数位(或者叫阶码),第三位为数据位(尾数)。
    计算机中的浮点数
    根据IEEE 754,在存入e的时候,必须在真实值的基础上加一个中间数(主要原因是因为小数点既可以往左移动(取负值),又可以往右移动(取正值))。对于单精度浮点数,中间数为127,对于双精度浮点数,中间数为1023。
    对于不同情况的描述如下:
    其中 case 4 可以表示最接近0的数
    { c a s e 1 : e = 255 , f ≠ 0 → x = N A N c a s e 2 : e = 255 , f = 0 → x = ( − 1 ) s ∞ c a s e 3 : e = 0 , f = 0 → x = ( − 1 ) s 0 c a s e 4 : e = 0 , f ≠ 0 → x = ( − 1 ) s ⋅ 2 − 126 × ( 0. f f . . . f ) c a s e 5 : 0 < e < 255 → x = ( − 1 ) s ⋅ 2 e − 127 × ( 1. f f . . . f ) \begin{cases} case 1: e=255, f \ne 0 \rightarrow x=NAN\\ case 2: e = 255, f = 0 \rightarrow x = (-1)^s \infin \\ case 3: e = 0, f = 0 \rightarrow x = (-1)^s 0\\ case 4: e = 0, f \ne 0 \rightarrow x = (-1)^s \cdot 2^{-126}\times (0.ff...f)\\ case 5: 0<e<255 \rightarrow x = (-1)^s\cdot 2^{e-127}\times(1.ff...f) \end{cases} case1:e=255,f=0x=NANcase2:e=255,f=0x=(1)scase3:e=0,f=0x=(1)s0case4:e=0,f=0x=(1)s2126×(0.ff...f)case5:0<e<255x=(1)s2e127×(1.ff...f)

浮点数的范围和误差分析

  • 最接近0的数(即表示0的误差),也是此时的最小变化量
    e = 0 时 , x = ± 2 − 126 × ( 0.00...1 ) = 2 − 149 ≈ 1.4012... × 1 0 − 45 e=0时,x = \pm2^{-126}\times(0.00...1) = 2^{-149} \approx 1.4012...\times 10^{-45} e=0x=±2126×(0.00...1)=21491.4012...×1045
  • 最接近1的数,可以准确表示1,此时最小变化量为 Δ = 2 − 23 \Delta = 2^{-23} Δ=223
    e = 127 时 , x = ± 2 0 × ( 1.00..0 ) = ± 1 e=127时,x = \pm 2^0 \times (1.00..0) = \pm 1 e=127x=±20×(1.00..0)=±1
  • 表示接近最大的数时,此时最小变化量 Δ = 2 127 − 23 = 2 104 \Delta = 2^{127-23} = 2^{104} Δ=212723=2104
    e = 254 时 , x = ± 2 127 × ( 1.11...0 ) ≈ ± 2 127 × ( 1.11...1 ) e = 254时,x = \pm 2^{127} \times ( 1.11...0) \approx \pm 2^{127} \times ( 1.11...1) e=254x=±2127×(1.11...0)±2127×(1.11...1)

所以用浮点数表示数时,一个浮点数的动态范围和其精度是不能兼得的。

附上一个知乎(真格量化)看到的图,图里简洁地表示出了,越靠近0,每一个离散点代表的实数范围越小,而越远离0,一个离散点代表的实数区域就越大。

计算机中的浮点数

例题1

这里附上课程ppt的一个典型问题:
答案为用定点法才可以准确计算。这是由于定点法刚好可以准确表示出0.1875,但是对于浮点数,在10之后,最小变化量 Δ = 0.25 \Delta=0.25 Δ=0.25,所以无法准确计算。

但这决不能说明定点法优于浮点法,只是一个题目的故意设计而已,体现出浮点数的精度问题而已。

计算机中的浮点数
计算机中的浮点数

用浮点数加法算算这里实际出来的结果

x = 1010 = 110, 0100 02
y = 0.187510 = 000, 110002

第一步,阶码对齐(移动5位)

y = 110, 0000 0110002

第二步 数据位(尾数相加)

∴ x + y = 0100 0 2 + 000001 1 2 = 010001 1 2 \therefore x+y = 0100 0_2 + 0000 011_2 = 0100 011_2 x+y=010002+00000112=01000112
加上阶码,整体结果为 110, 0100 011

第三部 截断(选择进一位)

最终结果为 110 0100 12 = 23 *1.010012 = 1010.012=10.25

计算机视觉课程与这里的联系

这里那一页上课的ppt作为例子,这是在计算两个平面的投影关系时导出的一个问题,下一步需要进行SVD分解。
但我们观察左边的矩阵,由于同时包含了1,x项,和xy这样相乘的二次项,会导致整个矩阵的数值相差巨大,对求解的数值稳定性和误差十分不友好。这就回到了上面我们说到的浮点数的取值范围和表示精度是不可兼得的
所以这里采取的一般做法都是把他转化到[-1,1]这样一个对称的区间,因为在[0,1],和[-1,0]这样的两个区间内部的精确度应该是一样的,所以为了不因为过度压缩导致的误差,采取这样一个对称区间进行计算。
计算机中的浮点数