Excess Notation 與儲存實數(含浮點數)的方法

歡迎你點入本篇文章,會促成我想做這篇的原因,主要是因為在上計概時,突然浮現很多靈感,跟一大堆的問題(教授,為什麼要講的這麼淺白呢?我想知道更多啊啊!),為了一次解決我所有的困惑,於是製作本篇文章。

另外本篇偏向於做題篇,原理部分可能點到為止。

若文章有任何疑點及錯誤的地方歡迎提出。

Excess Notation(移碼、偏移表示法)

Excess Notation(也叫超額表示法)主要用於浮點數的指數(exponent)部分。

原理是將實際的數值加上一個固定的偏移值(bias)(如 127 或 1023),使得所有可表示的數值都變成非負數,並以便於無符號(unsigned)方式儲存與比較。

於 Excess Notation 中,假設偏移量是 $N$ ,則實際要表示的數 $x$ 會轉成儲存值 $x{excess}$ 。 $$x{excess} = x + N$$

舉一個例子,IEEE 754 單精度浮點數的指數以 excess-127 表示(dash 後面的 127 就是偏移量),若指數為 $2$ 那儲存值就會是 $2 + 127 = 129$ 。

範例

以 excess-7 為例,求以下兩題的 excess notation :

(a) 4
(b) -3

Solution:

(a) 4 + 7 = 11,二進位表示為 1011。
(b) -3 + 7 = 4,二進位表示為 0100。

用途

  • 可以讓最小的二進位(如 $(00000000)_2$ )代表最小的值,而最大二進位(如 $(11111111)_2$ )代表最大值,方便硬體直接用整數比較大小。
  • 用於 IEEE 754 格式中的指數(exponent)欄位。
  • 避免判斷符號位元,儲存與運算都採用正整數。

儲存實數的方法

電腦儲存實數主要使用 IEEE 754 浮點數標準,將實數以二進位形式的編碼進行儲存。

(浮點數表示法)十進位轉二進位

以 23.625 為例。

看到這樣的數字可以先拆成 23 跟 0.625 分開計算。

23 的計算方式跟原本整數十進位轉二進位方法是一樣的:

  • 23 / 2 = 11 餘 1
  • 11 / 2 = 5 餘 1
  • 5 / 2 = 2 餘 1
  • 2 / 2 = 1 餘 0
  • 1 / 2 = 0 餘 1

所得二進位數字就是 $(10111)_2$ 。

再來計算 0.625,浮點數十進位轉二進位的方法大致如下:

  1. 小數部分乘以 2。
  2. 紀錄算完的結果之整數部分(0 跟 1)。
  3. 再把那個算完結果的小數部分拿出來繼續做第一步。
  4. 一直算算到變 0 後就結束了,將記錄到的整數部分由上到下依序排序。

用 0.625 計算的範例:

  • $0.625 \times 2 = 1.25$
  • $0.25 \times 2 = 0.5$
  • $0.5 \times 2 = 1.0$
  • $0.0 \times 2 = 0.0$

取整數部分即可得到 $(0.101)_2$ 。

最後整數 + 小數就會得到我們要的結果了, $(23.625)_{10} = (10111.101)_2$

二進位浮點數要怎麼轉回去十進位?

假設一個二進位浮點數是 $(1.101001)_2$ ,那轉回去十進位就要從最左邊開始,然後往右算。

首先整數部分 1,就是 $1 \times 2^0 = 1$ 。

再來小數部分:

  • $1 \times 2^{-1} = 1 \times 0.5 = 0.5$
  • $0 \times 2^{-2} = 0 \times 0.25 = 0$
  • $1 \times 2^{-3} = 1 \times 0.125 = 0.125$
  • $0 \times 2^{-4} = 0 \times 0.0625 = 0$
  • $0 \times 2^{-5} = 0 \times 0.03125 = 0$
  • $1 \times 2^{-6} = 0 \times 0.015625 = 0.015625$

最後相加起來就是答案了: $1 + 0.5 + 0 + 0.125 + 0 + 0 + 0.015625 = (1.640625)_{10}$

浮點數格式

浮點數是用科學記號的概念去做轉換的,主要將數值拆成三個部分去儲存:

註:MSB (Most significant bit)為最高位元,亦即最左邊的位元。

  1. 符號位(Sign bit, S):於 MSB 中,1 bit,0 表正數,1 表負數。
  2. 指數(Exponent, E):用 excess notation 編碼,單精度 8 位元,雙精度 11 位元。
  3. 尾數(Fraction/Mantissa, M):儲存有效數字的小數部分,單精度 23 位元,雙精度 52 位元。

(IEEE 754 採用正規化形式)另外在計算的時候要將這個浮點數進行正規化(Normalization),所謂正規化就是做以下動作:

將二進位數值轉換成 $(1.xxxxxxx)_2 \times 2^n$ ,確保小數點前都只有一個 1。

以 $(13.125)_{10}$ 執行正規化步驟:

  1. 轉二進位 $(13.125)_{10} = (1101.001)_2$
  2. 將 $(1101.001)_2$ 小數點移到最左邊那個 1 之後,變成 $(1.101001)_2$ 。
  3. 然後計算偏移量,就是看小數點移了幾位,這邊移了三位,所以偏移量是 3。
  4. 最後得到正規化結果就是: $(1.101001)_2 \times 2^3$ 。

如果最左邊那個位元不是 1 的話就是非正規化(denormal number 或 subnormal number)的數字,則會表示為 $(0.xxxxx)_2 \times 2^m$ 其中 m 為最小指數。這種數用來表示非常接近 0 的小數,避免下溢(Underflow)時直接變成 0。

浮點數分為兩種:

  • 單精度(float:single-precision floating-point)浮點數:32 位元,偏移量 127,有效位數約 7 位十進位數字。
  • 雙精度(double:Double-precision floating-point)浮點數:64 位元,偏移量 1023,有效位數約 15-16 位十進位數字。

轉換單精度浮點數

以 $13.125$ 為例:

  1. 首先轉成二進位 $(13.125)_{10} = (1101.001)_2$
  2. 進行正規化: $(1.101001)_2 \times 2^3$
  3. 由於 13.125 是正數,所以在符號位指定為 0。
  4. 接下來用 excess notation 計算指數: $E = 3 + 127 = (130)_{10} = (10000010)_2$
    • 這邊的 $3$ 是從正規化的 $2^3$ 中的指數來的。
  5. 尾數(M)取正規化的有效小數位: $M = 101001$
  6. 最終得到 0 10000010 10100100000000000000000

這樣子就轉換成 IEEE 754 標準的單精度浮點數了。這邊故意以空格區隔出符號位、指數位、尾數的部分。

由於要滿足單精度浮點數的 32 位元條件,因此在尾數填寫後,補足剩餘的 0 讓他到 32 位。

單精度浮點數轉回去實際數值

公式: $V = (-1)^S \times 2^{E-bias} \times (1.M)$ ,其中 V 為實際數值。

若 bit pattern 形式以 excess-127(8 位元浮點數儲存形式) 存儲之指數欄位,要轉回真實數值,步驟如下:

  1. 取得指數欄位的指數值(8 位元)。
  2. 減去偏移量(bias),如 $130 - 127 = 3$ 。
  3. 還原科學記號:將尾數(mantissa)還原成 $1.M$ 的形式。
  4. 接著使用上面的公式就可以了。(記得把 $1.M$ 轉成十進位,因為 $M$ 它本來就是二進位的形式)

舉個例子,假設有個 bit pattern 是 $(01000001010100100000000000000000)_2$ 。

看起來很長?先取出符號位,就是 MSB 那個 0。

然後再從它後面數八位元取出指數欄位,最後分隔一下就可以得到:

0 10000010 10100100000000000000000

而尾數 M 就是 101001。

最後我們整理一下得到的 S, E, M:

  • S = 0(正數)
  • E = $(10000010)_2$ = 130
  • M = $(101001)_2$

首先算出真正的指數, $E - bias = 130 - 127 = 3$ ,這個從 excess notation 的式子簡單移項就可以得到 3。

再來拼湊一下尾數,讓他變成 $1.M$ 的形式: $(1.101001)_2$ ,最後將這些東西代入公式就可以算出真實數值。

$V = (-1)^0 \times 2^3 \times (1.101001)_2 = 1 \times 8 \times 1.640625 = 13.125$

習題練習

  1. Show the number $(101001000000000000000000000000000.00)_2$ in floating-point representation.
  2. Show the number $−(0.00000000000000000000000101)_2$ in floating-point representation.
  3. Show the Excess-127 (single precision) representation of the decimal number $5.75$ .
  4. Show the Excess-127 (single precision) representation of the decimal number $–161.875$ .
  5. Show the Excess-127 (single precision) representation of the decimal number $–0.0234375$ .

總結

Excess Notation(偏移表示法):將實際數值加上固定偏移量(bias),使所有數值變成非負數。

計算公式: $x_{excess} = x + N$ ( $N$ 為偏移量)

這個表示法常用於 IEEE 表示浮點數時的指數欄位。

  • Excess-127:單精度浮點數(8 位元指數)
  • Excess-1023:雙精度浮點數(11 位元指數)

例:指數 3 在 excess-127 中儲存為 $3 + 127 = 130$


浮點數二進位轉換:

十進位轉二進位:

  • 整數部分: 2 取餘法(由下往上讀)
  • 小數部分: 2 取整法(由上往下讀)

二進位轉十進位:每位元乘以對應的 $2^n$ 次方後相加。

  • 整數部分: $n \ge 0$
  • 小數部分: $n < 0$

IEEE 754 浮點數格式:

部分單精度雙精度說明
符號位(S)1 bit1 bit0=正,1=負
指數(E)8 bits11 bits使用 excess notation
尾數(M)23 bits52 bits小數點後的有效數字
總計32 bits64 bits-
偏移量1271023-
精度約 7 位約 15-16 位十進位數字

正規化(Normalization)

格式: $(1.xxxxxxx)_2 \times 2^n$ (小數點前固定為 1)

步驟:

  1. (如果數字是十進位的話就轉)轉為二進位
  2. 移動小數點至第一個 1 之後
  3. 計算移動位數作為指數

如: $(1101.001)_2 → (1.101001)_2 \times 2^3$


十進位轉 IEEE 754 標準:

以 13.125 為例:

  1. 轉二進位 $(1101.001)_2$
  2. 正規化: $(1.101001)_2 \times 2^3$
  3. 符號位(S):0 (正數)
  4. 指數(E): $E=3+127=130=(10000010)_2$
  5. 尾數(M): $(101001)_2$ 補 0 到 23 位。
  6. 即得結果 0 10000010 10100100000000000000000

IEEE 754 再轉回去十進位:

公式: $V=(-1)^S \times 2^{E-bias} \times (1.M)$

步驟:

  1. 分離 S、E、M 三部分
  2. 計算真實指數,就是 $E-bias$ 的地方。
  3. 還原尾數為 $1.M$ 形式。
  4. 之後將 $(1.M)_2$ 轉成十進位。
  5. 代入公式計算

範例:0 10000010 10100100000000000000000

  • $S = 0, E=130, M=(101001)_2$
  • 真實指數 = $130 - 127 = 3$
  • $V = 1 \times 2^3 \times (1.101001)_2 = 8 \times 1.640625 = 13.125$

習題解答

  1. $1.01001 \times 2^{32}$
  2. $1.01 \times 2^{-24}$ (算 101 的前面有多少個 0)
  3. $01000000101110000000000000000000$
  4. $11000011001000011110000000000000$
  5. $10111100110000000000000000000000$