浮点数运算

在電腦科學中,浮點數運算(Floating-point arithmetic)是指以「浮點」(,縮寫為 FP)格式來表示實數並進行運算的一種方式。浮點是一種實數的近似數值表示法,由一個有效數字(即尾數)乘以特定基數的整數次指數(冪數)構成。以這種表示法表示的數值稱為浮點數()。由於電腦無法精確表示所有實數,浮點數運算通常會伴隨著近似值處理或捨入。

電腦採用浮點數運算的主因在於其底層的二進位制運算邏輯。例如:4 ÷ 2 = 2,轉換為二進位即 100(2) 變成 010(2),相當於將數值退一位數。同理,1.0 ÷ 2 = 0.5,二進位表示為 0.1(2),也就是 \frac{1}{2}。以此類推,二進位的 0.01(2) 即為十進位的 \frac{1}{2^{2}} = \frac{1}{4} = 0.25。由於十進位制中許多小數(如 0.1)無法精確轉換為有限位數的二進位小數,因此系統只能以近似值的方式來表達。

這種表示法類似於基數為 10 的科学记数法。在電腦上,通常使用 2 為基數,一個浮點數 a 可由尾數 m 與指數 e 表示為:a = m × be。在任意一個這樣的系統中,可選擇一個基數 b 與精度 p(即使用多少位元來儲存)。m(即)是格式如 ±d.ddd...ddd 的 p 位數(每一位數字介於 0 到 b-1 之間,包含 0 與 b-1)。若 m 的首位非 0,則稱該浮點數已正規化(Normalized)。實務上通常會使用獨立的符號位元(s 代表正或負)來表示正負號,此時 m 預設為正值。

這種設計基於對數值「表示範圍」與「精密度」之間的取捨:可以在某個固定長度的儲存空間內表示出某個實數的近似值。例如:一個指數範圍為 ±4 的 4 位十进制浮點數可以表示 43210、4.321 或 0.0004321,但沒有足夠的精確度來表示 432.123 和 43212.3(必須捨入近似為 432.1 和 43210)。當然,現代電腦實際使用的位數通常遠大於 4。

此外,浮點數表示法通常還包含一些特殊數值:+∞ 和 −∞(正負無窮大)以及 NaN(「Not a Number」,非數)。無窮大用於表示數值大到無法表示的狀況,NaN 則用來指示非法操作或無法定義的運算結果。

在記憶體中,無窮大(inf)的階碼(指數)為全 1,尾數為全 0;而 NaN 的階碼為全 1,尾數則不全為 0。

電腦的浮點數
浮點指的是帶有小數的數值,浮點運算即是小數的四則運算,常被用來測量電腦的運算速度。大部分電腦採用二進位(b=2)的表示方法。位元(bit)是衡量浮點數所需儲存空間的單位,通常為 32 位元或 64 位元,分別稱為單精度和雙精度。部分系統提供更大的浮點數,例如英特尔的浮點運算單元 Intel 8087协处理器(及其後續整合進 x86 處理器的產品)提供了 80 位元長的浮點數,用於儲存浮點運算的最後或中間結果。此外,也有一些系統提供 128 位元的浮點數(通常以軟體實現)。

浮點數的標準
電腦中使用的浮點數標準已被电气电子工程师协会(IEEE)規範化為 IEEE 754。

舉例
π 的值可以表示為 π = 3.1415926...10(十進位)。當在一個支援 17 位尾數的電腦系統中表示時,它會近似為 0.11001001000011111 × 22。

浮點數運算
為了方便閱讀與呈現,以下的例子將採用十進位、有效位數 7 位數的浮點數(類似 IEEE 754 decimal32 格式),其底層原理不會隨進位制或有效位數而改變。此處的 s 表示尾數(有效數字),e 表示指數。

加減法
處理浮點數加法的簡單作法是將兩個浮點數調整至具有相同的指數。在以下例子中,第二個數的小數點左移了三位,使兩者的指數相同,隨後即可進行一般的加法運算:

123456.7 = 1.234567 × 10^5
101.7654 = 1.017654 × 10^2 = 0.001017654 × 10^5

因此
123456.7 + 101.7654 = (1.234567 × 10^5) + (1.017654 × 10^2)
= (1.234567 × 10^5) + (0.001017654 × 10^5)
= (1.234567 + 0.001017654) × 10^5
= 1.235584654 × 10^5

若用 e 和 s 來表示:

e=5; s=1.234567 (123456.7)

  • e=2; s=1.017654 (101.7654)

e=5; s=1.234567

  • e=5; s=0.001017654 (對齊移位後)

e=5; s=1.235584654 (實際的和:123558.4654)

這是未經修約的真實結果。隨後系統會將其四捨五入到 7 位有效數字,並在需要時進行正規化,最終結果為:
e=5; s=1.235585 (最後答案:123558.5)

加數的最低三位數(654)在結果中被丟棄了,這種現象稱為捨入誤差。在一些極端的例子中,兩個浮點數相加的和,可能會與其中較大的一方完全相等:

e=5; s=1.234567

  • e=−3; s=9.876543

e=5; s=1.234567

  • e=5; s=0.00000009876543 (對齊移位後)

e=5; s=1.23456709876543 (真實的和)
e=5; s=1.234567 (四捨五入及正規化後)

在上述例子中,當兩數指數差距極大時,需要極高的精度才能獲得準確的結果。不過在二進位的加減法硬體設計中,只要利用保護位元(Guard bit)、捨入位元(Rounding bit)以及額外的黏滯位元(Sticky bit),即可確保捨入結果的正確性。

另一種嚴重失去有效數字的情形發生在兩個幾乎相等的數字相減時。在以下例子中,e = 5; s = 1.234571 和 e = 5; s = 1.234567 分別是有理數 123457.1467 和 123456.659 的近似值:

e=5; s=1.234571
− e=5; s=1.234567
----------------
e=5; s=0.000004
e=−1; s=4.000000 (四捨五入及正規化後)

如同所證明的,即使因為而出現下溢,浮點數的差仍可被精確計算。然而,原始兩數的真實差值約為 e = −1; s = 4.877000,這與浮點數運算得到的 e = −1; s = 4.000000 之間存在超過 20% 的誤差。在極端情況下,甚至所有的有效數字都可能完全消失。這種稱為灾难性抵消的現象顯示,若草率假設計算結果的每一位數字都是可靠的,將面臨極大風險。這類誤差的處理與修正是數值分析領域的核心課題之一。

乘除法
若要進行乘法,將有效數字相乘,指數相加,再進行四捨五入及正規化即可:

e=3; s=4.734612
× e=5; s=5.417242
-----------------------
e=8; s=25.648538980104 (真實乘積)
e=8; s=25.64854 (四捨五入後)
e=9; s=2.564854 (正規化)

除法則會將被除數與除數的有效數字相除,兩者的指數相減,接著再進行四捨五入及正規化。

乘除法運算通常不會面臨災難性抵消或大數吃小數的問題,但依然會產生捨入誤差。如果進行連續運算,這些誤差可能會逐步累積放大。實務上,要在硬體層面實現這類運算的數位邏輯相當複雜(例如布斯乘法算法與除法器設計)。

準確性
由於浮點數無法完美表達所有实数,浮點運算的結果與理論上的數學運算會有所差異,有時此差異甚至極為顯著。

例如,二進位浮點數無法精確表達 0.1 和 0.01。0.1 的平方既不是精確的 0.01,也不會是最接近 0.01 的可表達數值。單精度(24 位元有效數字)浮點數表示 0.1 的結果為 e=-4, s=110011001100110011001101_{(2)},其十進位真值為:
:0.100000001490116119384765625
此數值的平方為:
:0.010000000298023226097399174250313080847263336181640625
然而,在該系統中最接近 0.01 的可表達數值實際上是:
:0.009999999776482582092285156250

此外,浮點數也無法精確表達圓周率 \pi,因此在電腦上計算 \tan\frac{\pi}{2} 並不會得到正無窮大,也不會觸發溢位。以下方的 C 語言程式碼為例:

double pi = 3.1415926535897932384626433832795;
double z = tan(pi/2.0);

該計算結果為 16331239353195370.0;若改用單精度浮點數計算,結果則為 −22877332.0。同理,\sin \pi \neq 0。

由於浮點數計算過程中不可避免地會流失精度,浮點運算的代數性質與純數學運算並不相同,例如浮點數的加法與乘法皆不符合结合律與分配律。

歷史事故
早期 P5 世代的 60-100MHz 奔騰處理器在浮點運算單元(FPU)存在瑕疵。在極少數情況下,會導致除法運算的精確度大幅降低。這個硬體缺陷於 1994 年被發現,成為廣為人知的奔腾浮点除错误(Pentium FDIV bug)。此事件讓英特爾面臨巨大的公關危機,最終不得不啟動全面回收計畫來更換有缺陷的處理器。

相關條目

  • IEEE二進位浮點數算術標準(IEEE 754)
  • 單精度浮點數
  • 雙精度浮點數
  • MIPS
  • TOP500
  • 灾难性抵消

參考資料

评论 (0)

  • 还没有评论,来抢沙发吧。