參考:
http://jimmygod.blog.163.com/blog/static/43511339200792605627411/
http://blog.csdn.net/archersaber39/article/details/51422602
-------------------------------------------------------------------------------
我兩年前就知道不應該用==號來判斷浮點數的相等了,因為存在一個精度的問題,但是一直以來,都沒怎么在乎這些東西,而實際上,我對於浮點數的結構,雖然了解,但並不清晰. 作為一個C++愛好者,應該盡量搞清楚每一個問題,所以我搞清楚了浮點數的內在表示及實現.在沒有大問題的情況下,一切以易於理解和記憶為標准.
首先說一下原,反,補,移碼. 移碼其實就等於補碼,只是符號相反. 對於正數而言,原,反,補碼都一樣, 對負數而言,反碼除符號位外,在原碼的基礎上按位取反,補碼則在反碼的基礎之上,在其最低位上加1,要求移碼時,仍然是先求補碼,再改符號.
浮點數分為float和double,分別占4,8個字節,即32,64位. 我僅以32位的float為例,並附帶說double.
在IEEE754標准中,規定,float的32位這樣分:
| 符號位(S) 1 |
階碼(E) 8 |
尾數(M) 23 |
這里應該注意三點: A,階碼是用移碼表示的,這里會有一個127的偏移量,它的127相當於0,小於127時為負,大於127時為正,比如:10000001表示指數為129-127=2,表示真值為2^2,而01111110則表示2^(-1).
B, 尾數全都是小數點后面的數,
C, 但尾數中省略了一個1,因此尾數全為0時,也是1.0...00;
接下來只要說明幾個問題就明白了,以123.456為例,表示為二進制就是:N (2) = 1111011. 01110100101111001 ,這里,會右移6位,得到N (2) = 1.111011 01110100101111001*2^6; 這種形式就可以用於上圖中的表示格式了.
|
符號位(S) 0 |
階碼(E) 00000110 |
尾數(M) 11101101110100101111001 |
注意到,上面的階碼第一位為0表正,尾數比N(2)表示的第一位少了個1,這就是上面說的默認為第一位為1. 由於在將十進制轉為二進制的過程中,常常不能正好轉得相等, (當然,像4.0這樣的就不會有損失,而1.0/3.0這樣的必然損失),所以就產生了浮點數的精度問題, 實際上,小數點后的23位二進制數,能影響的十進制數的前8位,這是為什么呢?一般人在這時往往迷迷胡胡了,其實很簡單,在上面表示的尾數中,是二進制的,小數點后有23位,最后一位的值為1時,它就是1/2^22=0.000000238實際取的時候肯定是0.0000002,也就是說,對於一個float型的浮點數,其有效的位數是從左到右數7位(包括缺省的1才是7位),當到達上面這個第8位時,就不可靠了,但我們的VC6可以輸出最長的1.0/3.0為0.33333333333333331,這主要是編譯器的問題了, 而並不是說浮點數小數點后的16位都有效. 如果不信的話,可以去試一下double類型的1.0/3.0, 得到的也將是小數點后17位.
--------------------------------------
將20.163轉換成754標准的32位浮點數
1.將十進制數轉換成二進制數
十進制浮點數,整數部分轉換成二進制,采用除2取余法,將余數從低到高排列,即為整數的二進制數;
小數部分轉換成二進制,采用乘2取整法,將取整數順序排列,即為小數的二進制數。
小數部分乘2直到小數部分為0,或取到想要的位數,或循環出現前。
整數部分
20/2=10 .... 0
10/2=5 .... 0
5/2=2 .... 1
2/2=1 .... 0
1/2=0 ..... 1
小數部分
0.163*2=0.326 0
0.326*2=0.652 0
0.652*2=1.304 1
0.304*2=0.608 0
0.608*2=1.216 1
0.216*2=0.432 0
0.432*2=0.864 0
0.864*2=1.728 1
0.728*2=1.456 1
0.456*2=0.912 0
不要求精度時,通常取到8~10位
20.163=10100.0010100110
2.移動小數點到第1、2位之間,得e的值
10100.0010100110=1.01000010100110 *2的4次方 e=4(小數點移動4位)
3.求出S、E、M的值
S=0,E=4+127=131,M=01000010100110
S由小數點的后一位可以看出,0為正數,1為負數。
0 1000001 01000010100110000000000
IEEE754標准中32位浮點數表示
S E M
S是符號位占1位,E是階碼占8位,M是尾數占23位。
當尾數的值不為0時,尾數的最高有效位應為1,這稱為浮點數的規格化表示
這樣形式的叫規格化
新手初學,有問題或者錯誤,麻煩評論下 留言指正,謝謝
