衆所周知,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,也就是全零。若是轉換爲十進制,大約就是六、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規定:
一、表示小數點位置的部分若是全零,那麼這個浮點數的值爲0,而若是這個時候有效數字部分非零,那麼這個浮點數就「不是一個數」(NaN)
二、表示小數點位置的部分若是全一,那麼這個浮點數的值爲無窮大。
三、浮點數能表示的最大數值:表示小數點位置的部分除了最低位爲零其它均爲一,有效數字全爲1
四、浮點數能表示的最小數值:表示小數點位置的部分除了最低位爲一其它均爲零,有效數字全爲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_formatphp
https://www.0xaa55.com/forum.php?mod=viewthread&tid=462spa