IEEE浮點數float、double的存儲結構


眾所周知,C的float、VB的Single都是32位浮點數變量類型(也叫單精度浮點數),C的double和VB的Double則都是64位的浮點數變量類型(也叫雙精度浮點數)。有些編譯器還支持更屌的long double(貌似是80位還是128位的我不清楚,總之存在這種變態玩意兒。)那么這些浮點數從最底層的角度來看,它們是怎么存儲的呢?我來舉個例子解釋下。計算機用的是二進制,如果我用二進制跟大家解釋大家可能覺得看不懂,那我就用十進制來跟大家解釋。
浮點數分三個部分,第一個部分是有效數字,第二個部分給出小數點的位置,第三個部分用來判斷這個數是正數還是負數。舉例如下:
浮點數123.456
那么它用浮點數的存儲格式來表示就是:有效數字就是123456,小數點的位置在3的后面,然后它是正數。

那么我們要做的就是先取出有效數字123456,然后在3的后面插入小數點.就成了123.456,最后給它加個正號,就是+123.456了。

從二進制的方面來理解也是一樣的,比如我要表示-10101010.01010101,那么它的有效數字是1010101001010101,小數點在中間,然后它是負數。
上面我都只說了“小數點在中間”、“小數點在3后面”這種比較含糊的表達方法。那么浮點數到底是怎么存儲小數點的位置呢?這里我們要注意一整個浮點數中用來表示小數點位置的位數是多少。
還是用十進制來給大家舉個例子。假設我用兩個位來表示小數點的位置,那么兩個十進制位表示的最小的數是00,最大的數是99,我們總共能表達100個值。假設我要表達1234.5678,那么情況就是如下所示的:
有效數字是12345678
小數點的位置在中間。
這里我們用兩個十進制位來表示小數點的位置,那么這個小數點從左往右數(原來的數字是1234.5678)是在第四個位的后面。因此這兩個十進制位的值就是03。因為00表示從左往右數的第一個位的后面,01表示從左往右數的第二個位的后面,02表示從左往右數的第三個位的后面,那么03就表示從左往右數的第四個位的后面了。
有人可能會說“但是這樣一來我們不就無法表現小數了嘛。”其實不然。比如我們要表現0.233,那么我們就把有效數字設置成“0233”,然后小數點位置是00就行了。
對應的,二進制表示也是這樣的,比如我們用8個二進制位來表示小數點的位置,我們要表現的小數是10101010.01010101,那么小數點在從左往右數第八個位的后面,我們就用00001000來表示小數點的位置。

這里我就需要針對性地告訴大家,float和double是怎么回事。
float浮點數的有效數字是23位,小數點用8個位表示,然后符號(正、負)用一個位表示(0表示正、1表示負),總共組成32位。
因為float浮點數用8個位表示小數點的位置,因此小數點可以有256個位置。float浮點數規定從左往右數第127位的值必須是1,然后從第128位開始才是float的23位有效數字。因此float的浮點數的23位有效數字其實是從左往右數從第128位開始的。
我這里舉個例子:浮點數1.0f是怎么存儲的:
0 01111111 00000000000000000000000(0x3F800000)
其中藍色的部分是符號位,0表示正數。
黃色的部分表示小數點的位置,在從左往右數第127位處。
綠色部分是有效數字,共23個0,也就是全零。如果轉換為十進制,大約就是6、7個數位左右。
按照float浮點數的特性,第127位的值必須是1,然后存儲的23位有效數字的位置是在第128位開始的,我們把這個浮點數展開為256位,是這樣表示的:
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
前面的那些零和后面的那些零都是“虛構的”,也就是說這些零並沒有被存儲在float里面,而是同於補充位數的。第127位被強制設置為“1”,這是float的規定。
浮點數存儲了它的小數點位置:01111111,也就是“127”這里。那么我們最終得到的浮點數是:1.0

同樣的,double也是和float一樣用三個部分表示浮點數:有效數字,小數點位置,符號。
double的有效數字是52位,小數點位置用11個位表示,符號位用一個位表示。十進制可以精確到16個數位左右。
我這里舉個例子:浮點數1.0是怎么存儲的:
0 01111111111 0000000000000000000000000000000000000000000000000000(0x3FF0000000000000)
其中藍色的部分是符號位,0表示正數。
黃色的部分表示小數點的位置,在從左往右數第1023位處。
綠色部分是有效數字,共52個0,也就是全零。
按照double浮點數的特性,第1023位的值必須是1,然后存儲的52位有效數字的位置是在第1024位開始的,我們把這個浮點數展開為2048位,是這樣表示的:
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
在這2048位的數字中,我們的double存儲的52個有效數字在其中的綠色部分,也就是從1024位開始處。1023位被強制設置為1。可以看出,double的精度比起float提高了不少。
小數點的位置:01111111111表示小數點在第1023位的后面,因此最終得到的浮點數的數值是1.0

除了float和double,還有其它格式的浮點數:
Minifloat:迷你浮點數(8位):
1位符號位,4位小數點位置,3位有效數字。(PS.真夠“迷你”的)
Half:半精度(16位):
1位符號位,5位小數點位置,10位有效數字。
x86 Extended Precision Format:x86擴展精度格式(80位):
1位符號位,15位小數點位置,1位特殊位,63位有效數字。特殊位請看http://en.wikipedia.org/wiki/Extended_precision
Quadruple:四倍精度(128位):
1位符號位,15位小數點位置,112位有效數字。

IEEE規定:
1、表示小數點位置的部分如果全零,那么這個浮點數的值為0,而如果這個時候有效數字部分非零,那么這個浮點數就“不是一個數”(NaN)
2、表示小數點位置的部分如果全一,那么這個浮點數的值為無窮大。
3、浮點數能表示的最大數值:表示小數點位置的部分除了最低位為零其它均為一,有效數字全為1
4、浮點數能表示的最小數值:表示小數點位置的部分除了最低位為一其它均為零,有效數字全為0

參考資料
http://en.wikipedia.org/wiki/Minifloat
http://en.wikipedia.org/wiki/Half-precision_floating-point_format
http://en.wikipedia.org/wiki/Sin ... oating-point_format
http://en.wikipedia.org/wiki/Dou ... oating-point_format
http://en.wikipedia.org/wiki/Extended_precision
http://en.wikipedia.org/wiki/Qua ... oating-point_format

https://www.0xaa55.com/forum.php?mod=viewthread&tid=462


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM