小數表示法(定點法、浮點法)
——TechZone(Harris)
? 在計算機的數據存儲里面,常規思路來看,是只能表示有限位數的整數的。但是,無論是在日常生活中,還是在科學研究領域,小數(嚴格來講應該是分數)都是不可或缺的部分。那么,如何讓計算機能夠存儲并使用小數呢?這篇文章就帶大家一起來了解下兩種常用的小數表示法:定點法和浮點法。
定點數:用二進制來表示小數
? 其實,整數和小數的主要區別,我們可以不規范地理解為是否存在小數點,對吧?(其實整數也是有小數點的,我們這里暫且這么理解)那么要表示小數,只需要在整數表示的基礎上,加一個小數點,不就可以了嗎?沒錯,這就是定點數的思路。
? 定點數使用二進制,小數點的位置是事先約定好的,在使用的過程中不能改變,這也是定點數的名稱的由來。有的同學可能會問了,那么,小數如何從十進制換成定點數呢?不著急,且看下面的例子:
其實很簡單,和整數部分的完全相反。連續將小數部分的值乘以2,對于每一次得到的數,若整數為0,則順序記下一個0,若整數突破了1,則記下1,然后整數部分重置為0,小數部分繼續重復上述操作,直到小數部分為0為止。就像下面這樣:
十進制的0.125
0.125*2=0.25 (記下0)
0.25*2=0.5 (記下0,則目前為00)
0.5*2=1.0 (整數部分為1,記下1,則目前為001)
小數部分為0,轉換結束(這里是剛好結束,若整數位進一后小數部分還有剩余,則把整數部分變成0再繼續重復上面的算法)
則十進制0.125的二進制形式為0.001
二進制轉十進制:
? 看懂了吧,從小數點開始往右數,第一位小數的位權為-1,后面-2,-3以此類推。
? 二進制小數點向左移動一位,相當于這個數的數值除以2;相反,向右移動一位就是乘以2。
? 一般在現在計算機的應用中,定點數一般只有兩種情況,第一種是小數點在符號位之后,也就是表示純小數,第二種是在最后,也就是表示整數。這種表示方法的范圍并不大,如果需要表示類似于這樣的數值的話,那么用定點數的話就會占很大的空間。(畢竟你要很多很多個0才行,對吧)于是乎,我們的先人又開始秀智商了。
浮點數:表示更大范圍的小數
? 上面的例子我們已經看到了定點數的局限性,于是,先人們就祭出了浮點數大法,來讓我們更好地表示數(tuō)字(fà)。
? 如果上面的例子還不能夠說服你的話,我下面再舉個栗子:
表示一組數,0.123,1.23,12.3,123
? 如果此時你用定點數來表示的話,你會發現,這四組數字的表示方法完全不同。但是,我們的數學經驗卻又告訴我們,這幾個數字其實是可以用一種通式來表示的,你應該已經想到了,就是科學計數法。如果使用科學計數法,那么這幾組數字的通式可以表示為。貌似比什么定點數方便多了。
? 但是,我們知道,計算機是用來處理二進制的,那么,我們在二進制里面,可不可以打造一套類似于科學計數法的思路來表示小數呢——這就是浮點數的基本思路。浮點數的表示方法有點類似科學計數法,但是又比科學計數法要復雜。
? 不多廢話,我們來看看到底有什么貓膩。
? 在IEEE 754中,規定了浮點數用以下形式來表示:
? 有點懵?先不著急,首先這個公式的三個部分,分別是符號位*尾數*階碼
- 符號位(Sign):決定這個數是正數(S=0)還是負數(S=1);
- 尾數(Frac):決定這個數的精度以及主體部分,這里采用定點法表示;
- 階碼(Exp):決定這個數的范圍,它是一個加權值,權重是2的E次冪。
浮點數常用的有兩種:單精度浮點數和雙精度浮點數。
單精度浮點數用32bit來存儲,其結構如下:
| S(1bit) || Exp(8bit) || Frac(23bit) |
而雙精度浮點則使用64bit來存儲,結構如下:
| S(1bit) || Exp(11bit) || Frac(52bit) |
? 我們現在知道了浮點數的封裝結構,那我們接下來來了解下它是如何表示小數的。
-
規格化的值
當Exp字段不全為0或不全為1時,表示的就是規格化的值。這幾乎表示了絕大部分日常浮點數的情況。
此時,階碼使用移碼來表示。什么是移碼呢?我們要知道,Exp字段是表示無符號數字的,這樣更方便計算(不用涉及到反碼什么的)。但是,我們日常生活中,指數是可能為負數的,對吧?那么如何使用無符號的數字來表示有符號的數字呢?很簡單,加個偏移量就行了。比如我們現在要表示-5到+5的數字,但是我們必須要用無符號來表達,那么很自然,我們把這里面所有的數字都加個5,變成了0到10,那么系統要調用的時候,再把每個值都減去5即可。這個5實際上就是偏移量。那么這個偏移量我們怎么知道呢?記住公式即可
,其中Bias就是偏移量。既然都講到了Exp字段,自然是要來算指數了,那么指數E該怎么求出?還是公式:
,直接減去偏移量即可。
而Frac則用來表示尾數的(用定點數的方式表達,純小數)。尾數定為
,你可以理解為這種情況下,尾數中的1是白送的,加上去即可。
-
非規格化的值
當Exp字段全部為0時,就是非規格化的值,此時
,
。此刻,尾數的值就是小數的值,整數部分不是1而是0,這種情況用于表示很接近0.0的小數。
-
無窮大
當Exp字段全為1且Frac字段全為0時,則表示無窮大。若
則表示
,
則表示
。
-
NaN(Not a Number)
在無窮大的情況下
時,表示不是實數或者不能使用無窮大表示的情況。
說了那么多,大家估計也有點暈了,我們不妨再來兩個栗子看看到底該怎么使用上述的方法。
先看看浮點數轉為我們能看得懂的小數。
某天,Harris碰到了一個浮點數
1 01111100 11100000000000000000000
首先我們看到符號位,是1,說明這玩意兒是個負數,再看看階碼,雜亂無章,想必就是規格化的值了。好的,套方法。先把尾數轉化
,再白嫖個1,那么就是
。尾數部分搞定了,再看看指數。
偏移量,指數E于是就順水推舟
再利用上述的公式
上述方法大家應該都能看懂,我們再來看看我們常用的十進制小數如何轉化成浮點數表示。
來個簡單點的,就3.125吧。
首先,我們將這個小數用定點數的方法表示出來
完成轉換之后,我們可以得到,于是E就等于了1,尾數部分把白嫖的1還回去
假設我們轉換成單精度浮點,則偏移量,
又由于這貨是個正數,符號位是0,于是,浮點數表示就出來啦:
0 10000000 10010000000000000000000
其實還是挺簡單的,對吧?
? 好啦,今天的博客就到此結束了。這期實在是有點豐富,所以,一次性理解不了沒關系,多自己在紙上寫寫,也許就開竅了呢?