c語(yǔ)言單精度和雙精度的區(qū)別
單精度是這樣的格式,1位符號(hào),8位指數(shù),23位小數(shù)。
雙精度是1位符號(hào),11位指數(shù),52位小數(shù)。
區(qū)別就是它所能存儲(chǔ)的數(shù)值范圍大小不同,
雙精度變量能存儲(chǔ)比單精度變量更大或更小的值。
-- -- float 能賦值 +/- 3.40282e+038
-- -- double能賦值 +/- 1.79769e+308
含義:表明單精度和雙精度精確的范圍不一樣,單精度,也即float,一般在計(jì)算機(jī)中存儲(chǔ)占用4字節(jié),也32位,有效位數(shù)為7位;雙精度(double)在計(jì)算機(jī)中存儲(chǔ)占用8字節(jié),64位,有效位數(shù)為16位。
原因:不管float還是double 在計(jì)算機(jī)上的存儲(chǔ)都遵循IEEE規(guī)范,使用二進(jìn)制科學(xué)計(jì)數(shù)法,都包含三個(gè)部分:符號(hào)位,指數(shù)位和尾數(shù)部分。其中float的符號(hào)位,指數(shù)位,尾數(shù)部分分別為1, 8, 23. 雙精度分別為1, 11, 52。
精度主要取決于尾數(shù)部分的位數(shù),float為23位,除去全部為0的情況以外,最小為2的-23次方,約等于1.19乘以10的-7次方,所以float小數(shù)部分只能精確到后面6位,加上小數(shù)點(diǎn)前的一位,即有效數(shù)字為7位。 類似,double 尾數(shù)部分52位,最小為2的-52次方,約為2.22乘以10的-16次方,所以精確到小數(shù)點(diǎn)后15位,有效位數(shù)為16位。
單精度和雙精度數(shù)值類型最早出現(xiàn)在C語(yǔ)言中(比較通用的語(yǔ)言里面),在C語(yǔ)言中單精度類型稱為浮點(diǎn)類型(Float),顧名思義是通過(guò)浮動(dòng)小數(shù)點(diǎn)來(lái)實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)。這兩個(gè)數(shù)據(jù)類型最早是為了科學(xué)計(jì)算而產(chǎn)生的,他能夠給科學(xué)計(jì)算提供足夠高的精度來(lái)存儲(chǔ)對(duì)于精度要求比較高的數(shù)值。但是與此同時(shí),他也完全符合科學(xué)計(jì)算中對(duì)于數(shù)值的觀念:
當(dāng)我們比較兩個(gè)棍子的長(zhǎng)度的時(shí)候,一種方法是并排放著比較一下,一種方法是分別量出長(zhǎng)度。但是事實(shí)上世界上并不存在兩根完全一樣長(zhǎng)的棍子,我們測(cè)量的長(zhǎng)度精度受到人類目測(cè)能力和測(cè)量工具精度的限制。從這個(gè)意義上來(lái)說(shuō),判斷兩根棍子是否一樣長(zhǎng)絲毫沒(méi)有意義,因?yàn)榻Y(jié)果一定是False,但是我們可以比較他們兩個(gè)哪個(gè)更長(zhǎng)或者更短。這個(gè)例子很好地概括了單精度/雙精度數(shù)值類型的設(shè)計(jì)初衷和存在意義。
基于上述認(rèn)識(shí),單精度/雙精度數(shù)值類型從一開始設(shè)計(jì)的時(shí)候,就不是一個(gè)準(zhǔn)確的數(shù)值類型,他只保證在他這個(gè)數(shù)值類型的精度之內(nèi)是準(zhǔn)確的,精度之外則不保證,比方說(shuō),一個(gè)數(shù)值5.1,很可能存儲(chǔ)在單精度/雙精度數(shù)值中的實(shí)際值是5.100000000001或者5.09999999999999。導(dǎo)致這個(gè)現(xiàn)象的原因我們可以通過(guò)兩種方式來(lái)解釋:
簡(jiǎn)單的解釋方法:
你可以嘗試在任何一個(gè)控件的屬性面板中,設(shè)定他的寬度為:3.2CM,當(dāng)你輸入完畢后,你會(huì)發(fā)現(xiàn)值自動(dòng)變成了3.199cm,無(wú)論你怎么改,你都無(wú)法輸入3.200CM,因?yàn)閷?shí)際上在電腦中存儲(chǔ)的并不是CM為單位的數(shù)值,而是“緹”為單位的數(shù)值,而“緹”和CM之間的比值,是個(gè)很難被除盡的數(shù),因此你輸入完畢后,電腦自動(dòng)轉(zhuǎn)換成了最接近的“緹”值,然后再轉(zhuǎn)換成厘米顯示到屬性面板上,這一乘一除,兩次四舍五入,誤差就出來(lái)了。單精度/雙精度也是類似的原理,其實(shí)在二進(jìn)制存儲(chǔ)的時(shí)候,單精度/雙精度都采用了類似相近分?jǐn)?shù)的方法,而這樣的存儲(chǔ)是不可能做到準(zhǔn)確的。
深入的解釋方法:
讓我們來(lái)看看我們存儲(chǔ)到數(shù)字介質(zhì)中的單精度/雙精度值到底是怎么樣的,我們使用如下代碼對(duì)單精度類型進(jìn)行一個(gè)解剖:
Public Declare Sub CopyMemory Lib “kernel32” Alias
“RtlMoveMemory” (Destination As Any, Source As Any, ByVal Length As Long)
Public Sub floatTest() Dim dblVar As Single
dblVar = 5.731 / 8 dblOutput dblVar
dblVar = dblVar * 2 dblOutput dblVar
dblVar = dblVar * 2 dblOutput dblVar
dblVar = dblVar * 2 dblOutput dblVar
dblVar = dblVar * 2 dblOutput dblVar
dblVar = dblVar * 2 dblOutput dblVar
End Sub
Public Sub dblOutput(ByVal dblVar As Single) Dim bytVar(3) As Byte
Dim i As Integer, j As Integer Dim strVar As String
CopyMemory ByVal VarPtr(bytVar(0)), ByVal VarPtr(dblVar), 4 strVar = dblVar & “: ” For i = 3 To 0 Step -1 For j = 7 To 0 Step -1
strVar = strVar & (bytVar(i) And 2 ^ j) / 2 ^ j
Next j
strVar = strVar & “ ” Next i
Debug.Print strVar
End Sub
運(yùn)行后我們得到輸出結(jié)果(輸出格式為高位左,低位右):
.716375: 00111111 00110111 01100100 01011010 1.43275: 00111111 10110111 01100100 01011010 2.8655: 01000000 00110111 01100100 01011010 5.731: 01000000 10110111 01100100 01011010 11.462: 01000001 00110111 01100100 01011010 22.924: 01000001 10110111 01100100 01011010
這里,我們把單精度類型轉(zhuǎn)化成了二進(jìn)制數(shù)據(jù)輸出,這里我們看到,雖然這六個(gè)數(shù)字完全不同,但是他們的二進(jìn)制存儲(chǔ)驚人地相似,我們看到紅色標(biāo)記部分,每次都是加1,事實(shí)上,單精度數(shù)據(jù)類型使用從高位開始第1位作為正負(fù)標(biāo)記位(綠色),第2位到第9位,是一個(gè)跨字節(jié)的有符號(hào)字節(jié)類型數(shù)據(jù),這個(gè)數(shù)值決定了小數(shù)點(diǎn)移動(dòng)的方向和位數(shù)(紅色),第10位到32位保存一個(gè)整數(shù)(藍(lán)色)在存儲(chǔ)過(guò)程中,電腦首先把輸入的值不斷移位(乘除2)直到這個(gè)數(shù)的整數(shù)部分占用了全部24位的整數(shù)位,然后把移動(dòng)的位數(shù)寫入浮點(diǎn)部分(紅色),而移位后的結(jié)果寫入整數(shù)部分(藍(lán)色和綠色),小數(shù)部分則舍棄。求值的時(shí)候則是反向過(guò)程,先根據(jù)正負(fù)位和整數(shù)位求值,然后根據(jù)紅色部分的整數(shù)來(lái)進(jìn)行移位(乘除2的次方),最終才是我們得到的單精度數(shù)值。雙精度數(shù)值也是同樣原理,只是位數(shù)更多而已。
通過(guò)解剖單精度數(shù)值的二進(jìn)制存儲(chǔ)格式,我們可以清楚看到,實(shí)際上單精度/雙精度的存儲(chǔ),都要通過(guò)乘法和除法,其中必有舍入,如果恰好你的數(shù)值在除法中被舍入了,那么你賦的初值就很可能與你最終存儲(chǔ)的值不完全相同,其中的微小差異,并不與單精度/雙精度的設(shè)計(jì)目標(biāo)相違背。
當(dāng)我們?cè)跀?shù)據(jù)庫(kù)中或者VBA代碼中使用一個(gè)單精度/雙精度數(shù)值的時(shí)候,也許你從界面上看不到區(qū)別,但是在實(shí)際的存儲(chǔ)中,這個(gè)差別卻真真切切地就在那里,當(dāng)你對(duì)其進(jìn)行相等比較的時(shí)候,系統(tǒng)只是簡(jiǎn)單地作二進(jìn)制的比較,界面上無(wú)法體現(xiàn)的微小差異,在二進(jìn)制比較面前卻無(wú)處遁形,于是,你的等于比較返回了一個(gè)意料之外的False。
評(píng)論
查看更多