浮点数运算
| 浮点数运算 计算机数值编码 |
|---|
| IEEE 754 |
| 其它 |
|

在電腦科學中,浮點數運算(Floating-point arithmetic)是指以「浮點」(英語:floating point,縮寫為 FP)格式來表示實數並進行運算的一種方式。浮點是一種實數的近似數值表示法,由一個有效數字(即尾數)乘以特定基數的整數次指數(冪數)構成。以這種表示法表示的數值稱為浮點數(floating-point number)。由於電腦無法精確表示所有實數,浮點數運算通常會伴隨著近似值處理或捨入。
電腦採用浮點數運算的主因在於其底層的二進位制運算邏輯。例如:4 ÷ 2 = 2,轉換為二進位即 100(2) 變成 010(2),相當於將數值退一位數。同理,1.0 ÷ 2 = 0.5,二進位表示為 0.1(2),也就是 。以此類推,二進位的 0.01(2) 即為十進位的 = = 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),即可確保捨入結果的正確性[1][2]: 218–220 。
另一種嚴重失去有效數字的情形發生在兩個幾乎相等的數字相減時。在以下例子中,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 (四捨五入及正規化後)
如同Sterbenz 引理所證明的,即使因為漸進式下溢而出現下溢,浮點數的差仍可被精確計算。然而,原始兩數的真實差值約為 e = −1; s = 4.877000,這與浮點數運算得到的 e = −1; s = 4.000000 之間存在超過 20% 的誤差。在極端情況下,甚至所有的有效數字都可能完全消失[1][3]。這種稱為灾难性抵消的現象顯示,若草率假設計算結果的每一位數字都是可靠的,將面臨極大風險。這類誤差的處理與修正是數值分析領域的核心課題之一。
乘除法
若要進行乘法,將有效數字相乘,指數相加,再進行四捨五入及正規化即可:
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 (正規化)
除法則會將被除數與除數的有效數字相除,兩者的指數相減,接著再進行四捨五入及正規化。
乘除法運算通常不會面臨災難性抵消或大數吃小數的問題,但依然會產生捨入誤差。如果進行連續運算,這些誤差可能會逐步累積放大[1]。實務上,要在硬體層面實現這類運算的數位邏輯相當複雜(例如布斯乘法算法與除法器設計)。
準確性
由於浮點數無法完美表達所有实数,浮點運算的結果與理論上的數學運算會有所差異,有時此差異甚至極為顯著。
例如,二進位浮點數無法精確表達 0.1 和 0.01。0.1 的平方既不是精確的 0.01,也不會是最接近 0.01 的可表達數值。單精度(24 位元有效數字)浮點數表示 0.1 的結果為 , ,其十進位真值為:
- 0.100000001490116119384765625
此數值的平方為:
- 0.010000000298023226097399174250313080847263336181640625
然而,在該系統中最接近 0.01 的可表達數值實際上是:
- 0.009999999776482582092285156250
此外,浮點數也無法精確表達圓周率 ,因此在電腦上計算 並不會得到正無窮大,也不會觸發溢位。以下方的 C 語言程式碼為例:
double pi = 3.1415926535897932384626433832795;
double z = tan(pi/2.0);
該計算結果為 16331239353195370.0;若改用單精度浮點數計算,結果則為 −22877332.0。同理,。
由於浮點數計算過程中不可避免地會流失精度,浮點運算的代數性質與純數學運算並不相同,例如浮點數的加法與乘法皆不符合结合律與分配律。
歷史事故
早期 P5 世代的 60-100MHz 奔騰處理器在浮點運算單元(FPU)存在瑕疵。在極少數情況下,會導致除法運算的精確度大幅降低。這個硬體缺陷於 1994 年被發現,成為廣為人知的奔腾浮点除错误(Pentium FDIV bug)。此事件讓英特爾面臨巨大的公關危機,最終不得不啟動全面回收計畫來更換有缺陷的處理器。
相關條目
參考資料
- ^ 1.0 1.1 1.2 Goldberg, David. What Every Computer Scientist Should Know About Floating-Point Arithmetic (PDF). ACM Computing Surveys. March 1991, 23 (1): 5–48 [2016-01-20]. S2CID 222008826. doi:10.1145/103162.103163. (原始内容存档 (PDF)于2006-07-20).
- ^ Patterson, David A.; Hennessy, John L. Computer Organization and Design, The Hardware/Software Interface. The Morgan Kaufmann series in computer architecture and design 5th. Waltham, Massachusetts, USA: Elsevier. 2014: 793. ISBN 978-9-86605267-5 (英语).
- ^ 美国专利3037701A(于1962年6月5日注册)Huberto M Sierra——Floating decimal point arithmetic control means for calculator。