浮點數在計算機中的表示
最後編輯於:2010-4-13
計算機中數字是以0和1二進位制儲存的,我們熟悉的是整數的如何在計算機中表示,那麼浮點數是如何表示的呢?
一. 轉換
我們先來看看如何將十進位制的浮點數轉換成二進位制。
乙個十進位制的浮點數,例如:abcd.efg (其中a~g為0..9),其值用多項式為:
a*10^3 + b*10^2 + c*10^1+d*10^0+e*10^(-1)+f*10^(-1)+g*10^(-3)。
而乙個二進位制的浮點數,我們也將其表示成:abcd.efg (其中a~g為0或1),其值表示為:
a*2^3 + b*2^2 + c*2^1+d*2^0+e*2^(-1)+f*2^(-1)+g*2^(-3)。
我們看到底由十進位制時的10換成了二進位制時的2了,其它都一樣。所以乙個十進位制的浮點數轉換成二進位制必須分兩步進行:整數部分和小數部分。
1. 對於整數部分,和以前的整數轉換是一樣的。
2. 對於小數部分,比較特殊。下面講兩種轉換方法。
方法一:依次與2^(-n)作比較(n從1開始),若大於該值則為1,且減去此值,否則為0;然後繼續下一輪比較。舉例說明:將0.842356轉換成二進位制:
此時,你會發現比較將會是無窮無盡的。如果你擷取到某位,必須做一些取捨。取捨的標準是:其後一位若為1則進1;後一位為0則不進。還是以上面為例,若要擷取9位,因為第10位為0,故不進製,則最終的結果為:0.110101111;若要擷取到8位,因為第9位為1,故要進製,則最終的結果為:0.110110000(即0.1101101111 + 0.0000000001)。從這個例子可以看出十進位制小數的轉換成二進位制時只是乙個近似值。其實大部分浮點數儲存在計算機中都只是乙個近似值。至於是稍微大於原值還是稍微小於原值,要看擷取時有無進製。
方法二:若在計算機中計算方法一的過程,因為2^(-n)本身就是乙個浮點數,而浮點數之間的比較和計算難免有誤差。所以我想到了下面這個方法:
1) 首先生成首數字為1、後面0的個數為小數字數的基準數,比如0.254的基準數為1000、0.00353的基準數為100000。
2) 將小數部分乘以上面的基準數,這樣得到乙個整數。
3) 對該整數乘以2,若積大於基準數,則為1,同時將積減去基準數後得新的整數;若積小於基準數,則為0。
4) 用新的整數重複步驟3,直到整數為0或者到需要的精確位數,作取捨後結束。
舉例說明:將0.842356轉換成二進位制,基準數為1000000,轉換成整數為842356,
此法可以有效地避免浮點數的比較,能方便且快捷地獲得對應的二進位制值。
二. 儲存
現在已轉換成浮點二進位制了,那麼如何在計算機中表示呢?這要說到科學計數法,這個大家比較熟悉。十進位制的科學計算法可以表示成如下:(-1)^s * m * 10^e,s表示符號:s為1表示負數;0為正數。m成為尾數,其範圍為1<=m <10 。e被成為冪,也叫指數。
二進位制的科學計數法,也是ieee的浮點數標準格式,和十進位制格式一樣:(-1)^s * m * 2^e。m的範圍1<= m <2。將乙個二進位制浮點數轉換成科學計算法很簡單,例如:
1)10001.110001 小數點左移4位後成 (-1)^0 * (1.0001110001) * 2 ^ 4.
2) -0.000010001 小數點右移4位後成(-1)^1 * (1.0001) * 2 ^ ( – 4)
在計算機中,表示浮點數由兩種常用的格式:單精度浮點數和雙精度浮點數,它們在精度上有所差別,同時所需要的空間也有差別:
1) 當為負數時,符號位為1,否則為0。
2) 指數有正數亦有負數,這裡儲存時使用了加偏移量的方法:8位指數字的指數範圍為-127~128,其偏移量為127;11位指數範圍為-1023~1024,其偏移量為1023。儲存時指數加上偏移量,可以避免負數問題;取值時再減去偏移量就行了。
3) 因為尾數1<=m<2,就是說小數點前面總是有乙個1。為了節省空間,將此處的1省去,直接將小數點後面的部分放入到小數部分(這也是這部分為什麼叫「小數部分」,而不是「尾數部分」的原因)。
舉一例:將12.842356儲存成單精度浮點格式。
1) 首先將它轉換成二進位制格式:1100.11010111101001001010,後面位直接截去。
2) 轉換成科學計數法格式:1. 10011010111101001001010。右移3位於是指數為3+127=130,二進位制為10000010。
3) 於是符號位為0,指數為:10000010,小數去掉前面的1後為10011010111101001001010。這些二進位制就是最終儲存在電腦裡的格式:0 10000010 10011010111101001001010,十六進製制格式為:0x414d7a4a。
三. sql server中的浮點數
sql server浮點數有float和real兩種。float型別定義格式:float [ ( n ) ]。 n 為用於儲存科學記數法 float 數尾數的位數,同時指示其精度和儲存大小。n 必須為從 1 到 53 之間的值。
精度與儲存位元組之間的關係:
在 sql server 中,real 的同義詞為 float(24)。
比起其他的精確數值型別,浮點數的優點是儲存的數值大。比如單精度由於其指數為8位,故其最大值約為1.1 * 2^128 = 3.4 * 10^38;雙精度其指數為11位,故其最大值約為1.1 * 2^1024 = 1.79 * 10^308。
當然,浮點數的最大缺點就是資料的近似值儲存。就是這個原因,導致了下面的乙個小小的問題。
四. sql server中浮點數的乙個問題
因為float和real格式只能儲存近似值,除非要儲存特別大的數值,否則推薦使用精確數值型別。下面說說在sql server中遇到的乙個浮點問題,其實這也是為什麼寫這篇文章的原因。最近有人問下面這個問題:
declare @a, @b float
set @a = 1.465
set @b = 2.465
select round(@a, 2), round(@b, 2)
結果分別為1.47和2.46,這是為什麼?
上文中我們說過,大部分浮點數儲存在計算機中都只是乙個近似值。小數部分轉化成二進位制時,會根據情況截去或進製。
1.465儲存到計算機中時,小數的最後一位需要進製(結果為0x3ff770a3d70a3d71),這就造成了儲存的值比實際的1.465稍微大一點。0x3ff770a3d70a3d71轉換成十進位制後值約為1.4650000000000001。
而2.465卻正好相反,它在儲存到計算機中時,小數的最後一位後面直接截掉(結果為0x4003b851eb851eb8),這就造成了儲存的值比實際的2.465稍微小一點。0x4003b851eb851eb8轉換成十進位制後值約為2.4649999999999999。
round函式只是對儲存的值進行了四捨五入,沒有任何問題。若選擇使用精確數值型別,可以有效地避免這種問題的發生。
五. 參考文獻
計算機中浮點數的表示
浮點數就是有小數點的數。在c語言中有三種浮點數,分別為float,double和long double。下面分析一下其實現。include int main int argc,char argv 這是乙個簡單的c語言程式,定義了三個不同型別的變數a b c。編譯後用gdb除錯下 gdb p size...
計算機中浮點數的表示
在c語言中浮點數有兩個size,32位和64位。其中32位浮點數 第1位是signflag 符號位 2 9位是階碼位 exponent 10 32位是尾數字 significand 64位分別是第1位,2 12位,13 64位。浮點數大小的公式是 x 1 2 e m e exp 2 1 將 exp ...
浮點數在計算機中是如何表示的
相比int等整型,float等浮點型別的表示和儲存較為複雜,但它又是乙個無法迴避的話題,那麼就有必要對浮點一 竟了。在計算機中,一般用ieee浮點近似表示任意乙個實數,那麼它實際上又是如何表示的呢?下面的表示式裡,i的值是多少,為什麼?如果你不確定答案,那麼你應該好好看看本文。float f 8.2...