SQL Prompt根據數據庫的對象名稱、語法和代碼片斷自動進行檢索,爲用戶提供合適的代碼選擇。自動腳本設置使代碼簡單易讀--當開發者不大熟悉腳本時尤爲有用。SQL Prompt安裝便可使用,能大幅提升編碼效率。本文介紹了使用Float或Real數據類型的危險。程序員
浮點數據類型可容納很是大的數字,可是缺乏了精度。它們對於某些類型的科學計算很方便,可是在更普遍地使用時很危險,由於它們會引入較大的舍入偏差。算法
浮點運算就是爲了不計算中的溢出錯誤而容忍和管理近似。在現實世界中,咱們一般關心數字的準確性,而會犧牲空間和資源以免溢出。數據庫
科學是在偏差範圍內工做的,而精確在商業會計中相當重要。當我仍是一名初級程序員時,我曾經寫過一種我認爲是銀行計算交易利潤很是合適的方法。在一百萬英鎊中,最多也就一兩便士的偏差,我很滿意。它使用了咱們當時用來開發財務軟件包的PL / 1編譯器中固有的計算。我向他們展現了精心製做的應用程序,他們感到震驚。冷酷無情的銀行家們絕不留情地表示一百萬英鎊沒了幾分錢。他們不會接受的。我被迫用精確的彙編代碼編寫一個精確的二進制編碼的十進制(BCD)程序包。框架
SQL Prompt具備代碼分析規則(BP023),該規則將提醒您使用Float或Real數據類型,這是由於它們可能會引入許多組織一般在其SQL Server數據上常規執行的那種計算方式。ide
近似數的數據類型函數
浮點運算是在優先考慮節省內存的同時,提供了一種涉及大量運算的通用方法的時代設計出來的。儘管它對於許多類型的科學計算(尤爲是那些符合浮點算術雙精度IEEE 754標準的科學計算)仍然有用,但它必然是一種折衷方案。線索就是這種數據和算術的名稱:「近似」。浮點數不能精確表示全部實數:此外,浮點運算不能精確表示全部算術運算。可是,即便不老是精確地保留數字,它們能夠保留的數字的幅度範圍也遠大於其餘數字類型。測試
使用浮點運算引發的問題是因爲複雜計算過程當中的四捨五入而引發的,若是數據處於「不良條件」狀態,則最多見的問題就是輸入中的細微變化會在輸出中放大。隨着數字表示精度的提升,這種不精確性已經不那麼明顯了,可是它們仍然存在。在使用有效但不能用浮點數表示的數字時,還存在一些深奧的限制,例如tan(π/ 2),但這些可能僅會激發數學家的興趣。編碼
SQL Server浮點數據類型spa
SQL標準具備三個浮點,近似數據類型、REAL、DOUBLE PRECISION和FLOAT(n)。 SQL Server符合此要求,只是它沒有DOUBLE PRECISION數據類型,而改用FLOAT(53)。 FLOAT(24)和FLOAT(53)數據類型對應於IEEE 754標準中的Binary32(Single)和Binary64(double),並分別存儲在4和8字節中,並分別保留7和16位數字。當計算產生與使用還使用IEEE 754的.NET框架的應用程序相同的結果很重要時,它們頗有用。當數字的大小超過DECIMAL數據類型所容許的最大值(38位)時,還須要雙精度類型,但精度降低。固然,近似數不能可靠地用於任何相等性檢驗中,例如WHERE子句。設計
使用REAL數據類型的計算(單精度)
我將嘗試REAL數據類型。FLOAT(24)數據類型或更小的數據類型以相同的方式反應。在SQL Server中使用浮點數進行實驗時,要記住的第一件事是,SSMS以掩蓋微小差別的方式呈現浮點數。例如:
SELECT Convert(REAL,0.100000001490116119384765625)
…獲得0.1
爲了更準確地看到浮點數中存儲了什麼值,您必須使用STR()函數,指定實際須要的精度。
這已經使人擔心。畢竟,咱們正在處理具備數百萬行的數據,所以,除非像「銀行家四捨五入」之類的結果取平均值,不然小錯誤就會堆積起來。這個錯誤已經接近我在引言中提到的「百萬英鎊的便士」(1/240000000)!
讓咱們避免使用0.1,並將其歸結爲奇怪的浮點數。1除以3怎麼樣?這確定不是問題吧?
哎呀,它錯了。好的,這是一個很小的錯誤,但請記住我關於銀行家的故事。答案是對仍是錯,穿着灰色西裝的男人沒有灰色陰影。在商學院,只有一個標記和一個叉。沒有表示「足夠近」的標誌。
一個簡單的測試是將數字1除以1到20。會出什麼問題呢?
咱們能夠存儲浮點數和數值計算的結果,將它們都轉換爲字符串,而後比較字符串(請注意,字符串STR()能夠放在前導空格中,這會使狀況變得複雜)。
如今,若是咱們列出那些數字不匹配的行呢?
啊! 只有在除數爲一、二、四、8或16的狀況下,結果才正確。
若是您但願某種程度上的浮點數是準確的,而數值版本卻不正確,則如下是在Excel中計算出的數值商:
使用FLOAT(25)或更高(雙精度)的計算
若是使用雙精度浮點數FLOAT(25)或更高的精度,則全部測試都將經過,由於STR()函數最多容許小數點右邊16位。若是大於16,則結果將被截斷。雙精度數據類型具備16位數字,而單精度數據類型具備7位數字。您還將看到單精度數據類型正確獲取了前七個數字。一樣,雙精度會正確獲取前16位數字。咱們能夠擴大數字以查看近似值。
DECLARE @FirstApproximate FLOAT(53) = 10000000000000000.1 SELECT Str(@FirstApproximate,40,16) AS BigNumberWithaDecimal
那小部分消失了,不是嗎?這可能只是微小的差別,可是在某些計算中,它可能會引發問題。
結論
浮點算法在存儲上既快速又經濟,但提供了近似的結果。它適用於條件良好的科學應用,但不適用於財務計算,由於財務計算要求數字是「正確」或「錯誤」。它在數據庫中還具備額外的缺點,由於您不能可靠且一致地測試兩個近似數是否相等。
說永遠不要在SQL數據類型或算術中使用浮點數是不正確的。在SQL標準中,有一個特定的近似類型。現在,在有適當要求的SQL Server中,我始終堅持使用雙精度浮點數據類型。它們很是適合用於建模天氣系統或繪製軌跡等目的,但不適用於普通組織可能使用數據庫的計算類型。
若是發現錯誤使用了這些類型,則應改用合適的DECIMAL/ NUMERIC類型。若是您知道須要浮點算法並能夠解釋緣由,那麼您可能足夠了解避免浮點的陷阱。