浮點數

浮點數

數學術語
浮點數,是屬于有理數中某特定子集的數的數字表示,在計算機中用以近似表示任意某個實數。具體的說,這個實數由一個整數或定點數(即尾數)乘以某個基數(計算機中通常是2)的整數次幂得到,這種表示方法類似于基數為10的科學計數法。這種運算通常伴随着因為無法精确表示而進行的近似或舍入。
    中文名:浮點數 外文名: 定義: 英文名:Floating Point 分類:數學術語 範圍:有理數 數值:一個整數或定點數

簡介

一個浮點數a由兩個數m和e來表示:a=m×b^e。在任意一個這樣的系統中,我們選擇一個基數b(記數系統的基)和精度p(即使用多少位來存儲)。m(即尾數)是形如±d.ddd...ddd的p位數(每一位是一個介于0到b-1之間的整數,包括0和b-1)。如果m的第一位是非0整數,m稱作規格化的。

有一些描述使用一個單獨的符号位(s代表+或者-)來表示正負,這樣m必須是正的。e是指數。

由此可以看出,在計算機中表示一個浮點數,其結構如下:

這種設計可以在某個固定長度的存儲空間内表示定點數無法表示的更大範圍的數。

完成浮點加減運算的操作過程大體分為四步:

1、操作數的檢查;

2、比較階碼大小并完成對階;

3、尾數進行加或減運算;

4、結果規格化并進行舍入處理。

浮點加減運算過程比定點運算過程複雜。如果判知兩個操作數x或y中有一個數為0,即可得知運算結果而沒有必要再進行後續的一系列操作以節省運算時間。0操作數檢查步驟則用來完成這一功能。

兩浮點數進行加減,首先要看兩數的階碼是否相同,即小數點位置是否對齊。若二數階碼相同,表示小數點是對齊的,就可以進行尾數的加減運算。反之,若二數階碼不同,表示小數點位置沒有對齊,此時必須使二數階碼相同,這個過程叫作對階。

要對階,首先應求出兩數階碼Ex和Ey之差,即△E=Ex-Ey。

若△E=0,表示兩數階碼相等,即Ex=Ey;若△E>0,表示Ex>Ey;若△E<0,表示Ex

當Ex≠Ey時,要通過尾數的移動以改變Ex或Ey,使之相等。原則上,既可以通過Mx移位以改變Ex來達到Ex=Ey,也可以通過My移位以改變Ey來實現Ex=Ey。但是,由于浮點表示的數多是規格化的,尾數左移會引起最高有效位的丢失,造成很大誤差。尾數右移雖引起最低有效位的丢失,但造成誤差較小。

因此,對階操作規定使尾數右移,尾數右移後階碼作相應增加,其數值保持不變。顯然,一個增加後的階碼與另一個階碼相等,增加的階碼的一定是小階。因此在對階時,總是使小階向大階看齊,即小階的尾數向右移位(相當于小數點左移)每右移一位,其階碼加1,直到兩數的階碼相等為止,右移的位數等于階差△E。

對階結束後,即可進行尾數的求和運算。不論加法運算還是減法運算,都按加法進行操作,其方法與定點加減法運算完全一樣。

在浮點加減運算時,尾數求和的結果也可以得到01.ф…ф或10.ф…ф,即兩符号位不等,這在定點加減法運算中稱為溢出,是不允許的。但在浮點運算中,它表明尾數求和結果的絕對值大于1,向左破壞了規格化。此時将運算結果右移以實現規格化表示,稱為向右規格化。規則是:尾數右移1位,階碼加1。當尾數不是1.M時需向左規格化。

在對階或向右規格化時,尾數要向右移位,這樣,被右移的尾數的低位部分會被丢掉,從而造成一定誤差,因此要進行舍入處理。

簡單的舍入方法有兩種:一種是"0舍1入"法,即如果右移時被丢掉數位的最高位為0則舍去,為1則将尾數的末位加"1"。另一種是"恒置一"法,即隻要數位被移掉,就在尾數的末尾恒置"1"。

在IEEE754标準中,舍入處理提供了四種可選方法:就近舍入其實質就是通常所說的"四舍五入"。例如,尾數超出規定的23位的多餘位數字是10010,多餘位的值超過規定的最低有效位值的一半,故最低有效位應增1。若多餘的5位是01111,則簡單的截尾即可。對多餘的5位10000這種特殊情況:若最低有效位現為0,則截尾;若最低有效位現為1,則向上進一位使其變為0。

朝0舍入即朝數軸原點方向舍入,就是簡單的截尾。無論尾數是正數還是負數,截尾都使取值的絕對值比原值的絕對值小。這種方法容易導緻誤差積累。

朝+∞舍入對正數來說,隻要多餘位不全為0則向最低有效位進1;對負數來說則是簡單的截尾。

朝-∞舍入處理方法正好與朝+∞舍入情況相反。對正數來說,隻要多餘位不全為0則簡單截尾;對負數來說,向最低有效位進1。

浮點數的溢出是以其階碼溢出表現出來的。在加減運算過程中要檢查是否産生了溢出:若階碼正常,加(減)運算正常結束;若階碼溢出,則要進行相應處理。另外對尾數的溢出也需要處理。

階碼上溢超過了階碼可能表示的最大值的正指數值,一般将其認為是+∞和-∞。

階碼下溢超過了階碼可能表示的最小值的負指數值,一般将其認為是0。

尾數上溢兩個同符号尾數相加産生了最高位向上的進位,将尾數右移,階碼增1來重新對齊。

尾數下溢在将尾數右移時,尾數的最低有效位從尾數域右端流出,要進行舍入處理。

實例

此外,浮點數表示法通常還包括一些特别的數值:+∞和−∞(正負無窮大)以及NaN('Not a Number')。無窮大用于數太大而無法表示的時候,NaN則指示非法操作或者無法定義的結果。

衆所周知,計算機中的所有數據都是以二進制表示的,浮點數也不例外。然而浮點數的二進制表示法卻不像定點數那麼簡單了。

浮點數概念先澄清一個概念,浮點數并不一定等于小數,定點數也并不一定就是整數。所謂浮點數就是小數點在邏輯上是不固定的,而定點數隻能表示小數點固定的數值,具用浮點數或定點數表示某哪一種數要看用戶賦予了這個數的意義是什麼。

然而不同的編譯器對它們的支持也略有不同,據我所知,很多編譯器都沒有按照IEEE規定的标準80位支持後兩種浮點數的,大多數編譯器将它們視為double,或許還有極個别的編譯器将它們視為128位?!對于128位的long double我也僅是聽說過,沒有求證,哪位高人知道這一細節煩勞告知。

僅以float(帶符号,單精度,32位)類型的浮點數說明C++中的浮點數是如何在内存中表示的。先講一下基礎知識,純小數的二進制表示。(純小數就是沒有整數部分的小數,講給小學沒好好學的人)純小數要想用二進制表示,必須先進行規格化,即化為1.xxxxx*(2^n)的形式(“^”代表乘方,2^n表示2的n次方)。

針對在已獲得浮點數在内存中的二進制數據的條件下,如何獲取浮點數的十進制數據的問題,通過設計一個共用體類型實現内存中浮點數的二進制形式轉十進制的快速方法。

對于一個純小數D,求n的公式如下:n=1+log2(D);//純小數求得的n必為負數再用D/(2^n)就可以得到規格化後的小數了。接下來就是十進制到二進制的轉化問題,為了更好的理解,先來看一下10進制的純小數是怎麼表示的,假設有純小數D,它小數點後的每一位數字按順序形成一個數列:{k1,k2,k3,...,kn}。

那麼D又可以這樣表示:D=k1/(10^1)+k2/(10^2)+k3/(10^3)+...+kn/(10^n)。

推廣到二進制中,純小數的表示法即為:D=b1/(2^1)+b2/(2^2)+b3/(2^3)+bn/(2^n)。

例如0.456,第1位,0.456小于位階值0.5故為0;第2位,0.456大于位階值0.25,該位為1,并将0.456減去0.25得0.206進下一位;第3位,0.206大于位階值0.125,該位為1,并将0.206減去0.125得0.081進下一位;第4位,0.081大于0.0625,為1,并将0.081減去0.0625得0.0185進下一位;第5位0.0185小于0.03125。

最後把計算得到的足夠多的1和0按位順序組合起來,就得到了一個比較精确的用二進制表示的純小數了,同時精度問題也就由此産生,許多數都是無法在有限的n内完全精确的表示出來的,我們隻能利用更大的n值來更精确的表示這個數,這就是為什麼在許多領域,程序員都更喜歡用double而不是float。

符号就不用多說了,1表示負,0表示正指數是以2為底的,範圍是-128到127,實際數據中的指數是原始指數加上127得到的,如果超過了127,則從-128開始計,其行為和X86架構的CPU處理加減法的溢出是一樣的。

尾數都省去了第1位的1,所以在還原時要先在第一位加上1。它可能包含整數和純小數兩部分,也可能隻包含其中一部分,視數字大小而定。對于帶有整數部分的浮點數,其整數的表示法有兩種,當整數大于十進制的16777215時使用的是科學計數法,如果小于或等于則直接采用一般的二進制表示法。科學計數法和小數的表示法是一樣的。

判斷兩個浮點數是否相等。

在這個例子中我們以C++代碼來判别兩個浮點數是否相等。由于浮點數在存儲中無法精确表示,所以fp1==fp2無法準确的判斷float型變量fp1與fp2是否相等。應該使用(fp1-fl2)<0.0000001來進行判斷。

導數字分布

就隻有一個“随機”的浮點數而言,讨論其分布式沒有意義的,我們要讨論的是充分多個“随機”數進行的一系列運算後産生的浮點結果的前導數字分布。

假設現在有一巨大的浮點數集,依此對數集中每個浮點數都乘以2,其中有一個十進制浮點數F,它的前導數字是1,那麼它底數可能的值範圍就是1.000…~1.999…,乘以一個數字2,那麼它的底數就變成2.000…~3.999…,很明顯乘以2以前前導數字是1的浮點個數與現在前導數字是2、3的浮點個數相同。

對于一個b進制的浮點數,它的前導數字x範圍就是0

由前面所述的,對于一個充分小增量Δx,f(x)必須滿足這樣一個公式:f⑴Δx=x*f(x)Δx⑵。

因為:f⑴Δx是f⑴微分段内的概率,根據前面所述,f⑴Δx概率等于f(1*x)*(x*Δx)。

很明顯:f(x)=f⑴/x⑶。

兩邊在[1,b]之間進行積分,等号左邊必定為1,右邊等于f⑴ln(b):1=f⑴ln(b)⑷。

得:f⑴=1/ln(b)帶入⑶中:f(x)=1/(x*ln(b))。

那麼利用⑴式得:∫[u,v]1/(x*ln(b))dx=ln(v/u)/ln(b)⑸。

這就是求前導數字的概率分布函數。

相關詞條

相關搜索

其它詞條