浮點數,二進位浮點數,IEEE 754 二進位浮點數介紹

閱讀 9:19·字數 2799·發佈 
Youtube 頻道
訂閱 133

浮點數

浮點數是一種小數表示方式,其中“浮點”的含義為小數點是浮動變化的,這通常對應著指數的改變,因為浮點數儲存數值科學運算質的相關資訊,包括指數,尾數等項目。

為何使用浮點數?

總的來說,浮點數是一種平衡方案,兼顧了擴大數值描述範圍和節省儲存空間,因為通過指數可以表示更趨向於0或無限大的數值,而其自身占用的空間又很小。

假設浮點數采用了十進位,那麽描述0.000000000001234小數點後面大量的0,只需儲存其科學運算質1.234×10⁻¹²中的指數-12,而不是為每個0分配真實的儲存空間。

二進位浮點數

目前的浮點數硬體普遍采用二進位,這是由於 IEEE 754-1985 標準的流行,該標準僅規定了浮點數的二進位儲存格式。而在 IEEE 754-1985 出現之前,浮點數的格式並不統一,有些硬體支援十進位甚至三進位格式的浮點數。

雖然後來的 IEEE 754-2008 加入了浮點數的十進位儲存格式,但改變不會輕易發生,因為這對於硬體廠商意味著風險。

不同進位浮點數所儲存的指數和尾數

理所當然的,對於不同進位的浮點數,其儲存的指數和尾數資訊,應來自於對應進位的科學運算質,否則會給計算帶來不必要的麻煩。

比如,將小數12.3轉換為采用十進位的浮點數,如果確定使用科學運算質1.23×10¹,那麽指數應該可以換算為十進位的1,尾數應該可以換算為十進位的1.23

二進位浮點數不準確

事實上因為進位的轉換問題,采用二進位的浮點數具有不準確性,你可以檢視為何二進位浮點數不準確?IEEE 754 二進位浮點數拾入規則一節了解相關資訊。

IEEE 754 二進位浮點數

同樣是依賴科學運算質和二進位格式,不同的設計方案可能導致浮點數的表現大相徑庭,IEEE 754 定義了二進位浮點數符號,指數,尾數的格式,他們依次排列並占用 4,8 或更多個位元組的儲存空間。

IEEE 754 二進位浮點數符號格式

符號占用 1 個 bit 的儲存空間,為1時表示浮點數是一個負數,為0時表示浮點數是一個非負數。

IEEE 754 二進位浮點數指數格式

指數在 4/8 位元組浮點數中占用 8/11 個 bit 的儲存空間,指數在儲存之前需要計算為指數編碼值,計算方法為科學運算質中的指數真實值加上指數位移值。指數位移值的計算公式是2ⁿ⁻¹-1n為指數占用的 bit 個數,4/8 位元組浮點數的指數位移值為127/1023

使用指數編碼值是為了方便表示指數為負的情況,假設在 4 位元組的浮點數中,指數儲存的二進位內容為01111011(對應十進位數值為123),那麽指數編碼值就是123,指數真實值就是123-127,即-4

此外,除了參與正常運算,指數編碼值還用於判斷特殊值或特殊格式是否成立。

IEEE 754 二進位浮點數尾數格式

尾數在 4/8 位元組浮點數中占用 23/52 個 bit 的儲存空間,當尾數不等價於0並且指數編碼值對應的十進位數值大於等於0小於2ⁿ⁻¹-1(其中n表示指數在儲存空間中占用的 bit 個數)時,尾數最高位將被隱藏,不會真正儲存在浮點數中。這種做法使得尾數節省出 1 個 bit 的儲存空間,而且不會影響運算,因為根據指數編碼值可以得知被隱藏的尾數最高位是0還是1

十進位的0.5對應的二進位科學運算質為1×10⁻¹(其中的數位01均為二進位,10對應了十進位的2),尾數最高位1被省去後,其在 4 位元組浮點數中的儲存內容將是00000000000000000000000(僅尾數部分)。

IEEE 754 二進位正規和次正規浮點數

如果指數編碼值對應的十進位數值大於0小於2ⁿ⁻¹-1(其中n表示指數在儲存空間中占用的 bit 個數),則浮點數屬於正規浮點數,被隱藏的尾數最高位為1。正規浮點數是最為常見的,其二進位科學運算質中的尾數最高位總是為1

如果指數編碼值等價於0,尾數儲存的二進位內容不等價於0,則浮點數屬於次正規浮點數,被隱藏的尾數最高位為0,指數真實值由0-(2ⁿ⁻¹-1)改為0-(2ⁿ⁻¹-1)+1(其中n表示指數在儲存空間中占用的 bit 個數)。

IEEE 754 二進位次正規浮點數的作用是什麽?

次正規浮點數用於表示比正規浮點數更趨近於0的小數,因為其隱藏的尾數最高位為0,對應的二進位科學運算質尾數為純小數而非混合小數,等同於變相增加了指數範圍,而這一範圍是正規浮點數指數無法到達的。

在次正規浮點數對應的二進位科學運算質中,出現在尾數小數點後以及尾數第一個1之前的0越多,指數變相增加的範圍就越大。為了方便說明,我們以十進位科學運算質0.00003×10⁻³⁸為例,他等同於3×10⁻⁴³,指數變相由-38成為了-43

IEEE 754 二進位浮點數特殊值的表示

當指數編碼值和尾數儲存的二進位內容均等價於0時,浮點數表示數值0

當指數編碼值對應的十進位數值等於2ⁿ⁻¹-1時(其中n表示指數在儲存空間中占用的 bit 個數),則將根據尾數決定浮點數表示的特殊值,尾數儲存的二進位內容等價於0表示無限大,不等價於0表示非數值NaN

程式設計語言中的二進位浮點數型別

幾乎所有的程式設計語言都實作了 IEEE 754 標準的二進位浮點數,比如,C# 中的floatdouble型別,Python 中的float類別。這樣做的好處是可以利用同樣采用 IEEE 754 二進位格式標準的浮點數硬體,隨著浮點數硬體效能的升階,程式執行的效率會得到改善。

運算規則不適用於浮點數型別

浮點數使用有限的儲存空間來表示極大範圍的數值,因此數值中的一些數位可能會被忽略。從這個角度講,浮點數是一種近似值,他無法保證某些運算規則的正確性。比如,當xy不相等時,a+xa+y未必不相等,因為xy可能在加法運算後被忽略。

在 C# 中,浮點數0.00000000000000000001f不等於浮點數0.00000000000000000002f,而1.0f+0.00000000000000000001f卻可以等於1.0f+0.00000000000000000002f,因為小數部分在加法運算後被忽略。

*.cs
// 不相等,輸出 False
Console.WriteLine(0.00000000000000000001f == 0.00000000000000000002f);
// 相等,輸出 True
Console.WriteLine(1.0f + 0.00000000000000000001f == 1.0f + 0.00000000000000000002f);
False
True

二進位浮點數的近似性與不準確無關

二進位浮點數不準確的根源是進位的轉換,而近似則是其本身的設計理念,如果提供足夠的儲存空間,近似的情況可能會消失。

程式設計語言中的十進位浮點數型別

在程式設計語言中,並非所有的浮點數型別都采用了 IEEE 754 的二進位格式,比如,C/C++ 編譯器 GCC 支援的_Decimal32_Decimal64_Decimal128,他們是十進位格式的浮點數型別。十進位浮點數型別沒有二進位浮點數型別不準確的問題,因此可用於精確計算,比如,統計銀行存款。

程式設計語言中十進位浮點數型別的運算效率

雖然十進位浮點數型別沒有了不準確的問題,但其運算效率可能不及二進位浮點數,因為缺少浮點數硬體的有效支援。硬體可能無法直接運算十進位數值,而是需要其自身或軟體進行某種轉換,這降低了運算效率。

當然,如果有需求,不排除未來一些浮點硬體升階十進位浮點數運算能力。

內容分類

程式碼

floating.cs·codebeatme/programming-reference·GitHub