C++浮點型的存儲方式詳解
浮點型及其存儲方式
有些時候需要變量能存儲帶小數點的數,或者能存儲極大數或極小數。這類數可以用浮點(因小數點是“浮動的”而得名)格式進行存儲。C語言提供瞭3種浮點類型,對應三種不同的浮點格式。
當精度要求不嚴格時(小數點後少於六位),float類型是很適合的類型。double提供更高的精度, 對絕大多數程序來說夠用瞭。longdouble支持極高精度的要求,很少會用到。
C標準沒有說明float、double和long double類型提供的的精度到底是多少,因為不同計算機可以用不同方法存儲浮點數。大多數現代計算機遵循IEEE754標準(即IEC 60559) 的規范,所以這裡也將它作為一個示例。
一、IEEE浮點標準
由IEEE開發的IEEE標準提供瞭兩種主要的浮點數格式:單精度(32位) 和雙精度(64位)。數值以科學記數法的形式存儲,每一個數都由三部分組成:符號、指數和小數。指數部分的位數說明瞭數值的可能大小程度,而小數部分的位數說明瞭精度。單精度格式中,指數長度為8位,而小數部分占瞭23位。因此,單精度數可以表示的最大值大約是3.40×1038,其中精度是6個十進制數字。
IEEE標準還描述瞭另外兩種格式:單擴展精度和雙擴展精度。標準沒有指明這些格式中的位數,但要求單擴展精度類型至少為43位,而雙擴展精度類型至少為79位。
類型 | 最小值 | 最大值 | 精度 | 備註 |
---|---|---|---|---|
●float | 1.175 49×10-38 | 3.402 82×1038 | 小數點後6位 | 單精度32位 |
●double | 2.225 07×10-308 | 1.797 69×10308 | 小數點後15位 | 雙精度64位 |
上表給出瞭根據IEEE標準實現的浮點類型特征。[表中給出瞭規范化的最小正值, 非規范化的數可以更小。] long double類型沒有顯示在此表中, 因為它的長度隨著機器的不同而變化,而最常見的大小是80位和128位。
二、存儲方式
對於浮點型數據,首先我們需要明白的一點是:浮點數和整型數的編碼方式是不一樣的,IEEE浮點標準采用如下形式來標識一個浮點數。
V = (-1)S M 2E
- (-1)S 表示符號位,當S=0時,表示正數,當S=1時,表示負數。
- M 表示有效數字,是一個二進制小數,其值大於等於1,小於2。
- 2E 表示指數位。
下面,我將用float作為例子,double道理也是一樣的,隻是位數有所不同。
例如:十進制數:88.8125 —> 二進制為:101 1000.1101
然後將101 1000.1101化成上述公式M的形式,其范圍是[1,2),所以將小數點左移6位,得到1.0110001101×26(這裡不懂的話對比十進制,小數點左移一位乘以10,二進制則乘以2)。
最後得到S = 0、M = 1.0110001101、E = 6,但是事情並沒有那麼簡單,我們接著往下看。
IEEE 754對有效數字M和指數E的規定。
1、有效數字M:
1<=M<2,也就是說,M寫成1.xxx……的形式,其中xxx……表示小數部分。
IEEE 754規定,在計算機內部保存M時,默認這個數的第一位總是1,因此可以被舍去,隻保存小數部分。比如保存1.0110001101時,隻保存0110001101,後面的位數補0就可以瞭,等到讀取的時候,再把第一位的1補上去。
2、指數E:
首先,E為一個無符號整數(unsigned int)
如果E為8位,它的取值范圍為0~255;如果E為11位,它的取值范圍為0~2047。但是,我們知道,科學計數法是可以出現負數的,所以IEEE 754規定,存入內存的E是真實值加上一個中間數,對於8位的E,中間數是127,對於11位的E,中間數是1023。比如,26 的E是6,所以保存為32位浮點數時,必須保存為6+127=133,即10000101。
重點:
結合上述補充的信息完善例子
float:
十進制數:88.8125 二進制為:101 1000.1101 == 1.0110001101×26
- 符號位:0
- 指數位:6+127=133 二進制為:1000 0101
- 小數位:1.0110001101去掉最高位1則為:0110001101
因此浮點數88.8125的IEEE浮點表示為:
—-0—-1000 0101—-011 0001 1010 0000 0000 0000
符號位- -指數域- – – – – – – – – – -小數域
根據指數域不同取值分為一下三種情況:
1)E不全為0或不全為1(規格化值)
這是最常見情況,取出內存中的數時,指數E的計算值減去127(或1023),得到真實值,再將有效數字M前加上第一位的1。
2)E全為0(非規格化值)
這時,浮點數的指數E等於1-127(或1-1023)即為真實值,有效數字M不再加上第一位的1,而是還原為0.xxxxxxx的小數。這樣做是為瞭表示正負零,以及接近於0的很小的數字。
舉個例子:編碼為如下情形:
0 0000 0000 000 0000 0000 0000 0000 0001
即2(-23)×2(-126)=2(-149),轉成10進制大約等於1.4×10(-45),這就是單精度所能表達最小的正數瞭。
3)E全為1(特殊數值)
當指數域全為1時屬於這種情形。此時,如果小數域全為0且符號域S=0,則表示正無窮,如果小數域全為0且符號域S=1,則表示負無窮。如果小數域不全為0時,浮點數將被解釋為NaN, 即不是一個數(Not a Number) 。比如計算負數平方根或處理未初始化數據時。
總結
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!