之前的一些工作當中碰到了很多有關浮點數的問題,比如浮點數的表達範圍、表達精度、浮點數的儲存方式、浮點數的強制型別轉換等等,因此感覺有必要系統了解一下有關浮點數的問題。
浮點數是一種公式化的表達方式,用來近似表示實數,並且可以在表達範圍和表示精度之間進行權衡(因此被稱為浮點數)。
浮點數通常被表示為:
\(n = m\times r^e\)
比如: \(12.345 = 1.2345\times 10^1\)
其中,m(mantissa)被稱為浮點數的尾數,r(radix)被稱為階碼的基數,e(exponent)被稱為階的階碼。計算機中一般規定r為2、8或16,是乙個確定的常數,不需要在浮點數中明確表示出來。
因此,在已知標準下,要表示浮點數,
一是要給出尾數m的值,通常用定點小數形式表示,它決定了浮點數的表示精度,即可以給出的有效數字的位數。
二是要給出階碼,通常用定點整數形式表示,它指出的是小數點在資料中的位置,決定了浮點數的表示範圍。因此,在計算機中,浮點數通常被表示成如下格式:(假定為32位浮點數,基為2,其中最高位為符號位)
按照上面的指數表示方法,乙個浮點數會有不同的表示:
\(0.3\times10^0\);\(0.03\times10^1\);\(0.003\times10^2\);\(0.0003\times10^3\);
為了提高資料的表示精度同時保證資料表示的唯一性,需要對浮點數做規格化處理。
在計算機內,對非0值的浮點數,要求尾數的絕對值必須大於基數的倒數,即\(|m|\ge \frac\)。
即要求尾數域的最高有效位應為1,稱滿足這種表示要求的浮點數為規格化表示:把不滿足這一表示要求的尾數,變成滿足這一要求的尾數的操作過程,叫作浮點數的規格化處理,通過尾數移位和修改階碼實現。
比如,二進位制原碼的規格化數的表現形式:(0正1負)
正數0.1******
負數1.1******
注意,尾數的最高位始終是1,因此我們完全可以省略掉該位。
至此,我們引入ieee754 標準,該標準約束了浮點數的大部分使用設定:(尾數用原碼;階碼用「移碼」;基為2)
(1) 尾數用原碼,且隱藏尾數最高位。
原碼非0值浮點數的尾數數值最高位必定為 1,因此可以忽略掉該位,這樣用同樣多的位數就能多存一位二進位制數,有利於提高資料表示精度,稱這種處理方案使用了隱藏位技術。當然,在取回這樣的浮點數到運算器執行運算時,必須先恢復該隱藏位。
(2) 階碼使用「移碼」,基固定為2
如下圖的32bit浮點數和64bit浮點數,從最高位依次是符號位、階碼和尾數
於是,乙個規格化的32位浮點數x的真值為:
\(x = (-1)^s\times(1.m)\times2^\)
乙個規格化的64位浮點數x的真值為:
\(x = (-1)^s\times(1.m)\times2^\)
下面舉乙個32位單精度浮點數-3.75表示的例子幫助理解:
(1)首先轉化為2進製表示
\(-3.75 = -(2+1+1/2+1/4) = -1.111\times2^1\)
(2)整理符號位並進行規格化表示
\(-1.111\times2^1 = (-1)^\times(1+0.1110\ 0000\ 0000\ 0000\ 0000\ 000)\times2^1\)
(3)進行階碼的移碼處理
\((-1)^\times(1+0.1110\ 0000\ 0000\ 0000\ 0000\ 000)\times2^1\)
\(=(-1)^\times(1+0.1110\ 0000\ 0000\ 0000\ 0000\ 000)\times2^\)
於是,符號位s=1,尾數m為\(1110\ 0000\ 0000\ 0000\ 0000\ 000\)階碼e為\(128_=1000\ 0000_2\),則最終的32位單精度浮點數為
\(1\ 1110\ 0000\ 0000\ 0000\ 0000\ 000\ 1000\ 0000\)
通過上面的規格化表示,我們可以很容易確定浮點數的表示範圍:
既然有表示範圍,那肯定也有不能表示的數值:
首先來說明溢位值,如下圖:
(1)無窮值:
如果指數\(e=11111111_2=255_\)且尾數\(m=0\),則根據符號位s分別表示\(+\infty\)和\(-\infty\)。因此,乙個有效的32位浮點數其指數最大只能為254。
此外,無窮具有傳遞性,比如
(+∞) + (+7) = (+∞)
(+∞) × (−2) = (−∞)
(+∞) × 0 = nan
(2)零值:
如果指數\(e=0\)且尾數\(m=0\)時,表示機器0.需要注意的是,這裡的0也是有符號的,在數值比較的時候 \(+0=-0\); 但在一些特殊操作下,二者並不顯相等,比如\(\log(x)\), \(\frac \neq \frac\)。
此外,處於負下溢位和負上溢位之間的數值會被直接歸為0。
(3)nan:
如果\(e=0\)且尾數\(m\neq 0\),則表示這個值不是乙個真正的值(not a number)。nan又分成兩類:qnan(quiet nan)和snan(singaling nan)。qnan與snan的不同之處在於,qnan的尾數部分最高位定義為1,snan最高位定義為0;qnan一般表示未定義的算術運算結果,如\(\frac\), \(\infty \times 0\), \(sqrt(-1)\);snan一般被用於標記未初始化的值,以此來捕獲異常。
一般提到浮點數的精度(有效位數)的時候,總是會出現float的有效位為6~7位, double的有效位為15~16位。
下面以float為例,解釋一下有效位數是怎樣來的。
有效位數只和規格化浮點數的尾數部分有關,而尾數部分的位數是23位,因此我們首先列出下表
由上面的**可以看出:
\(2^\) 和 \(2^\) 之間是存在間隔的,即0.0000001和0.0000002之間的小數我們是沒有辦法描述的,因此23位尾數最多只能描述到小數點後第7位;此外,我們通過四捨五入可以很容易發現\(0.0000003 = 0.0000004 = 2^+2^\), 這表明第7位有效數字只是部分準確。而第6位及之前的都是可以準確描述的,因此我們說float的有效位為6~7位。
(1) wiki 詞條 「floating point」:
(2) wiki 詞條 「ieee floating point」:
(2) 浮點異常值:nan,qnan,snan:
IEEE的浮點數表示
ieee浮點標準用v 1 s m 2 e 由符號,尾數,階碼表示 32位單精度 單精度二進位制小數,使用32位儲存。1 8 23 位長 s exp fraction 31 30 23 22 0 位編號 從右邊開始為0 偏正值 127 64位雙精度 雙精度 二進位制小數,使用64位儲存。1 11 52...
C51浮點數顯示 浮點數表示方法
c51中的浮點數儲存方式 n年前曾在c51bbs論壇中發布過 float 浮點形,它是符合ieee 754標準的單精度浮點形資料,在十進位制中具有7位有效數字。float型據占用四個位元組 32位二進位制數 在記憶體中的存放格式如下 位元組位址 由低到高 0 1 2 3 浮點數內容 mmmmmmmm...
析IEEE浮點數表示法
眾所周知,計算機中的所有資料都是以二進位制表示的,浮點數也不例外。然而浮點數的二進位制表示法卻不像定點數那麼簡單了。先澄清乙個概念,浮點數並不一定等於小數,定點數也並不一定就是整數。所謂浮點數就是小數點在邏輯上是不固定的,而定點數只能表示小數點固定的數值,具用浮點數或定點數表示某哪一種數要看使用者賦...