浮點型
浮點型
在計算機系統的發展過程中,曾經提出過多種方法表示實數,但是到目前為止使用最廣泛的是浮點表示法。相對於定點數而言,浮點數利用指數使小數點的位置可以根據需要而上下浮動,從而可以靈活地表達更大範圍的實數。
浮點數是一串0和1構成的位序列(bit sequence),從邏輯上用三元組{S,E,M}表示一個數N,如下圖所示:
浮點數公式1
浮點數公式2
N的實際值n由右邊的式子表示:
其中:
★ n,s,e,m分別為N,S,E,M對應的實際數值,而N,S,E,M僅僅是一串二進位位。
★ S(sign)表示N的符號位。對應值s滿足:n>0時,s=0; n≤0時,s=1。
★ E(exponent)表示N的指數位,位於S和M之間的若干位。對應值e值也可正可負。
★ M(mantissa)表示N的尾數位,恰好,它位於N末尾。M也叫有效數字位(significand)、係數位(coefficient), 甚至被稱作"小數"。
浮點數表示法利用科學計數法來表達實數(real),當計算的表達式有精度要求時被使用。例如,計算平方根,或超出人類經驗的計算如正弦和餘弦,它們的計算結果的精度要求使用浮點型。在IEEE標準754之前,業界並沒有一個統一的浮點數標準,直到1985年Intel打算為其的8086微處理器引進一種浮點數協處理器時,才請加州大學伯克利分校的 William Kahan教授──最優秀的數值分析家之一來為8087 FPU設計浮點數格式; 而這個傢伙又找來兩個專家來協助他,於是就有了KCS組合(Kahan, Coonan, and Stone)。他們共同完成了Intel的浮點數格式設計,而且完成地如此出色,以致於IEEE組織決定採用一個非常接近KCS的方案作為IEEE的標準浮點格式。目前,幾乎所有計算機都支持該標準,大大改善了科學應用程序的可移植性。C標準規定的浮點型有float、double、long double,和整型一樣,既沒有規定每種類型佔多少位元組,也沒有規定採用哪種表示形式。浮點數的實現在各種平台上差異很大,有的處理器有浮點運算單元(FPU,Floating Point Unit),稱為硬浮點(Hard-float)實現;有的處理器沒有浮點運算單元,只能做整數運算,需要用整數運算來模擬浮點運算,稱為軟浮點(Soft-float)實現。大部分平台的浮點數實現遵循IEEE 754,float型通常是32位,double型通常是64位。 long double型通常是比double型精度更高的類型,但各平台的實現有較大差異。在x86平台上,大多數編譯器實現的long double型是80位,因為x86的浮點運算單元具有80位精度,gcc實現的long double型是12位元組(96位),這是為了對齊到4位元組邊界,也有些編譯器實現的long double型和double型精度相同,沒有充分利用x86浮點運算單元的精度。其它體系結構的浮點運算單元的精度不同,編譯器實現也會不同,例如PowerPC上的long double型通常是128位。
以前我們只用到最簡單的浮點數常量,例如3.14,現在看看浮點數常量還有哪些寫法。由於浮點數在計算機中的表示是基於科學計數法的,所以浮點數常量也可以寫成科學計數法的形式,尾數和指數之間用e或E隔開,例如314e-2表示314×10的-2次方,注意這種表示形式基數是10,如果尾數的小數點左邊或右邊沒有數字則表示這一部分為零,例如3.e-1,.987等等。浮點數也可以加一個後綴,例如3.14f、.01L,浮點數的後綴和類型之間的對應關係比較簡單,沒有後綴的浮點數常量是double型的,有後綴f或F的浮點數常量是float型的,有後綴l或L的浮點數常量是long double型的。
名稱 | 位數 | 數的範圍 |
double | 64 | 1.7E–308~1.7E+308 |
float | 32 | 3.4E–38~3.4E+38 |
下面討論浮點型的兩種類型。
1 .單精度浮點型(float)
單精度浮點型(float )專指佔用32位存儲空間的單精度(single-precision )值。單精度在一些處理器上比雙精度更快而且只佔用雙精度一半的空間,但是當值很大或很小的時候,它將變得不精確。當你需要小數部分並且對精度的要求不高時,單精度浮點型的變數是有用的。例如,當表示美元和分時,單精度浮點型是有用的。
這是一些聲明單精度浮點型變數的例子:float hightemp,lowtemp;
2 .雙精度浮點型(double )
雙精度型,正如它的關鍵字“double ”表示的,佔用64位的存儲空間。在一些現代的被優化用來進行高速數學計算的處理器上雙精度型實際上比單精度的快。所有超出人類經驗的數學函數,如sin( ),cos( ) ,tan()和sqrt( )均返回雙精度的值。當你需要保持多次反覆迭代的計算的精確性時,或在操作值很大的數字時,雙精度型是最好的選擇。
具體有三種形式:
IEEE754三種浮點數的格式參數
類型 存儲位數 偏移值
數符(s) | 階碼(E) | 尾數(M) | 總位數 | 十六進位 | |
短實數(Single,Float) | 1位 | 8位 | 23位 | 32位 | 0x7FH +127 |
長實數(Double) | 1位 | 11 位 | 52位 | 64位 | 0x3FFH +1023 |
臨時實數(延伸雙精確度,不常用) | 1位 | 15位 | 64位 | 80位 | 0x3FFFH +16383 |
對於階碼為0或為255(2047)的情況,IEEE有特殊的規定:
如果 E 是0 並且 M 是0,這個數±0(和符號位相關)如果 E = 2 − 1 並且 M 是0,這個數是 ±無窮大(同樣和符號位相關)如果 E = 2 − 1 並且 M 非0,這個數表示為不是一個數(NaN)。
標準浮點數的存儲在尾數中隱含存儲著一個1,因此在計算尾數的真值時比一般形式要多一個整數1。對於階碼E的存儲形式因為是127的偏移,所以在計算其移碼時與人們熟悉的128偏移不一樣,正數的值比用128偏移求得的少1,負數的值多1,為避免計算錯誤,方便理解,常將E當成二進位真值進行存儲。例如:將數值-0.5按IEEE754單精度格式存儲,先將-0.5換成二進位並寫成標準形式:-0.510=-0.12=-1.0×2-12,這裡s=1,M為全0,E-127=-1,E=12610=011111102,則存儲形式為:
1 01111110 000000=BE000000(16)
這裡不同的下標代表不同的進位。
浮點數(也叫浮點數,雙精度數或實數)可以用以下任何語法定義:
形式上:
LNUM [0-9]+DNUM ([0-9]*[/.]{LNUM}) | ({LNUM}[/.][0-9]*)EXPONENT_DNUM ( ({LNUM} | {DNUM}) [eE][+-]? {LNUM})
轉換為浮點數
如果希望了解有關何時和如何將字元串轉換成浮點數的信息,請查閱“將字元串轉換為數值”一節。對於其它類型的值,其情況類似於先將值轉換成整型,然後再轉換成浮點。請參閱“轉換為整型”一節以獲取更多信息。自 php 5 起,如果試圖將對象轉換為浮點數,會發出一條通知。