作为计算机中数字的单精度二进制浮点表示的先驱,我首先讨论十进制数的所谓“科学记数法”。
使用以 10 为底的数字系统,每个正十进制数在集合 {1..9} 中都有第一个非零前导数字。 (所有其他数字都在集合 {0..9} 中。)数字的小数点总是可以通过乘以数字基数 10 的适当幂 10^n 来移动到该前导数字的最右边。例如0.012345 = 1.2345*10^n 其中 n = -2。这意味着每个非零数 x 的十进制表示可以采用以下形式
x = (+/-)(i.jklm...)*10^n ; where i is in the set {1,2,3,4,5,6,7,8,9}.
前导小数因子(i.jklm...),称为x的“尾数”,是区间[1,10)中的一个数,即大于等于1且小于10。尾数的最大值可以是 9.9999... 所以数字 x 的实际“大小”是存储在指数因子 10^n 中的整数。如果 x 很大,则 n >> 0,而如果 x 很小,则 n
我们现在想使用与计算机存储数字相关的以 2 为底的数字系统来重新审视这些想法。计算机内部使用以 2 为底的数字表示数字,而不是更熟悉的以 10 为底的数字。数字的“二进制”表示中使用的所有数字都属于集合 {0,1}。使用与我们在十进制表示中相同的思维方式以二进制表示形式表示 x,我们看到每个正数 x 都具有以下形式
x = (+/-)(i.jklm...)*2^n ; where i = 1,
而其余数字属于 {0,1}。
这里领先的二进制因子(尾数)i.jklm...位于区间[1,2),而不是与十进制系统中尾数相关的区间[1,10)。此处尾数以二进制数 1.1111... 为界,它始终小于 2,因为实际上永远不会有无限位数。和以前一样,数字 x 的实际“大小”存储在整数指数因子 2^n 中。当 x 很大时 n >> 0 并且当 x 非常小时 n
x 的(单精度)二进制表示的标准约定是通过在计算机内存中准确存储 32 位(0 或 1)来实现的。第一位用于表示数字的算术“符号”。这使得 31 位要分布在 x 的尾数 (i.jklm...) 和指数因子 2^n 之间。 (回想一下 i.jklmn 中的 i = 1 ......所以它的表示不需要 31 位中的任何一个。)此时,一个重要的“权衡”开始发挥作用:
专用于 x 的尾数 (i.jkl...) 的位越多,可用于在其指数因子 2^n 中表示指数 n 的位就越少。通常 23 位专用于 x 的尾数。 (不难证明,在十进制系统中,x 的精度大约为 7 位,这对于大多数科学工作来说已经足够了。)由于第一个位专门用于存储 x 的符号,因此剩下 8 位可用于表示因子 2^n 中的 n。由于我们希望允许非常大的 x 和非常小的 x,因此决定以
的形式存储 2^n
2^n = 2^(m-127) ; n = m - 127,
存储指数 m 而不是 n。利用 8 位,这意味着 m 属于二进制整数集合 {000000,00000001,....11111111}。由于人类更容易在十进制系统中思考,这意味着 m 属于值集合 {0,1,....255}。减去-127,这意味着2^n又属于数集{-127,-126,...0,1,2...128},即
-127 <= n <= 128.
x 的二进制浮点表示的最大指数因子 2^n 可以被视为 2^n = 2^128,或者在十进制系统中查看(使用任何计算器计算 2^128)
2^n <= 3.4028...*10^38.
综上所述,在IEEE格式的计算机中,单精度浮点数可能存储的最大数x是形式为的数
x = y*(3.4028...*10^38).
这里尾数 y 位于(半闭半开)区间 [1,2) 中。
为简单起见,Matlab 将“最大”可能的浮点数的“大小”报告为指数因子 2^128 = 3.4028*10^38 的最大大小。从这个讨论中我们看到,使用 32 位二进制浮点表示可以存储的最大浮点数实际上加倍为 max_x = 6.8056*10^38。