2008年12月27日 星期六

這..這算是SQL SERVER的bug嗎?

考考大家一個很簡單再不行的數學題.
 20000 * 1.11 / 4 / 10 後,無條件進位 等於多少........................................ 如果你不笨應該算出 555 這個數值,
但如果在SQL SERVER 環境中在無條件進位前的結果是 float ,如果這時取無條件進位時所出現的數值絕對讓你意想不到..
下列 Script 你可以先自己試算後再到 SQL SERVER 中執行一下,看看是你笨還是它笨。

   1:  Declare @A int,@B float,@C int,@D int,@E int
   2:  Set @A = 20000
   3:  Set @B = 1.11
   4:  Set @D = 4
   5:  Set @E = 10
   6:   
   7:  Select Ceiling(@A * @B / @D / @E)



執行完後的結果是--------------------------------------------------------->>> 556 ???
對於這種現象該說是微軟的錯還是我們不懂它的好(就像是Delphi 的 Round 一樣), 我提出一個我較能接受的分析是....  float 本身是一種近似數值資料類型,所以以往存在後端 Float 型態欄位常會出現 1.25 --> 1.24999999 or  1.24 --> 1.240000000001 , 這不是 bug 而是 float 的特性,所以當一連串運算後型態轉成 float 時(隱含轉型),可能會造成運算結果已不是我們看到的那樣子,後面可能還掛著 0.000000001 吧,這時再Ceiling時自然而然就進一位了,所以 Script 改成 下列所述後就不會有問題。

   1:  Declare @A int,@B float,@C int,@D int,@E int
   2:  Set @A = 20000
   3:  Set @B = 1.11
   4:  Set @D = 4
   5:  Set @E = 10
   6:   
   7:  Select Ceiling(CAST(@A * @B / @D / @E as decimal(20,10))) 



不知道那些偉大的程式設計師會不會修正這個問題或是這是一種”正常”,不過以後有用到這種運算式的就小心點用了。

1 則留言:

小佩 郭 提到...

講實在話我很不想看這個題目, 因為我不想動腦, 不過有件事忘了跟你說~~~就是:生日快樂 身體健康"其實本來這句話不會遲到的, 但因為手機的日期慢了所以忘了提醒我啦, 你就包涵一下囉..加油 再拼第三胎...Penny