浮點數!好困難喔!每次都搞不懂甚麼叫倍精數,甚麼叫做單精數!O_o?
對的,在電腦 0 與 1 的世界中,要表現出無限小數是有其困難點與複雜度的。一般我們在計算小數點幾位的精確度,頂多也只到小數點 5, 6 位而已,如單價低的貨品,需要賣出大量的貨才會有利潤,這時候你的單價可能需要準確到小數點第五位,但這對電腦來說也是輕而易舉的事情。
那複雜的是甚麼呢?
如果您是要計算天文的距離,這時候小數點的精確度問題就會浮現,正所謂 失之毫釐 差之千里,就是這個意思。
OK,讓我們進入浮點數的單元吧!
.避免對相差懸殊的數做加減運算
當您在做以下的運算時,可能會得不到正確的結果,
1000000.00+0.01 可能會得到1000000.00的結果
不過這是以前的程式語言中可能發生的問題,現在的Compiler對這個部份都可以做到很好的運算結果。
我們也可以將小數整數化,透過長整數來做運算,如:
(1000000*100+0.01*100)/100
這個觀念,我們在底下的四捨五入中會使用到。
.避免做"等於"的比較運算
看起來應該是相等的兩個浮點數,可能會有不相等的結果!這是因為,用不同的方法所製造出來的浮點數的值不見得一定相等。書中的例子,0.1加十次不一定會是1.0
dim Nominal as single
dim Sum s single
dim i as integer
Nominal=1.0
Sum=0
for i=1 to 10
Sum=Sum+0.1
next i
if Nominal=Sum then
Msgbox "兩個數是相同的"
else
Msgbox "兩個數是不同的"
end if
這樣可能得到兩個數是不相同的結果
我們可以透過以下的方式來避免這個問題
const AcceptableDelta=0.00001
if abs(Nominal-Sum)<AcceptableDelta then
Msgbox "兩個數是相同的"
else
Msgbox "兩個數是不同的"
end if
或者使用內建比較函數 equals 來做為比較的運算
if Nominal.equals(Sum)
.避免四捨五入的誤差
四捨五入的問題,跟前一段所提的問題很類似,撇開書中所舉的例子,我要來談談實際運用面如何解掉一些可能發生的問題。
四捨五入有很困難嗎?不是都有提供四捨五入的函數,例如 Round?
是這樣沒錯,但是您知道他的運作原理嗎?
一般我們要取小數兩位的數時,我們通常會這樣寫
x=round(y,2)
就數學上的運算來說,四捨五入就是 +0.5 做無條件捨去
我們要取小數點兩位,可以做如下的運算
dim x as single
x=Cint(y*100+0.5)
x=x/100
這樣就可以避免掉浮點數計算中可能會遇到的誤差問題
其實,這個觀念是我的大師兄告訴我的,當初聽到的時候,真是如獲至寶,果然是大師兄才會得到師父的真傳(回憶中...)
回神啦!趕快去準備明天的進度啦!
國慶日耶
一大早就上電腦概論...
這麼專業的東西
還是交給panc328大大來comment吧...
今天是國慶?
Sorry 最近只專注在因應大陸十一長假的議題
都忘了...XD
http://en.wikipedia.org/wiki/IEEE_754-2008
http://zh.wikipedia.org/zh-tw/IEEE_754
以前也碰過這類的計算問題...感謝。
感謝 fillno 大的補充 ^^
我以前在公司討論Float重點是在非常非常小的值的情形下.
如果以資料庫來說.一般寫沖帳的程式,如果在int情形下數值等於0的時候表示這一筆交易已被結案.但如果是Float情形下可能剩餘值不等於但趨近於0的情形.所以你要做趨近於0為結案的算法.
而就資料庫而言在值趨近於0時,這個值會是一個不確定的值.他會在某個區間值.所以在查詢時可能下條件不是=而要下A>=值<=B.
另外已Float去做大數值的運算.結果會有某些偏差.比如說小數幾位下x好幾百億的值後結果就不正確.那時候我們老闆有舉例.好像做國防部的案子,資金好幾百億,在做利息運算時.最後的金額跟原本的金額只差幾塊錢而已就會出現問題.
所以說科學中可以用Float.在商業程式還是用Decimal 或Money去存.雖然空間浪費較大.但結果較精準.
我目前只處理過幾十億的 case ...XD
pantc328 大說得沒錯,在商業環境的資料庫中,還是以 decimal 或 numeric 的型態為主