2013-08-31 28 views
3

在寫科學應用的功能MySQL的精密型問題,我遇到了問題。我追溯到MySQL缺乏精確性。在十進制數字化數據類型

以下是來自官方文檔的頁面,聲明DECIMAL的最大位數是65 - http://dev.mysql.com/doc/refman/5.6/en/fixed-point-types.html。它還描述瞭如果值超過指定的精度,值將如何舍入。

這裏是可重複的代碼(MySQL存儲功能),以測試它 -

DELIMITER $$ 
    DROP FUNCTION IF EXISTS test$$ 
    CREATE FUNCTION test 
     (xx DECIMAL(30,25) 
    ) 
     RETURNS DECIMAL(30,25) 
     DETERMINISTIC 
    BEGIN 
     DECLARE result DECIMAL(30,25); 
     SET result = 0.339946499848118887e-4; 
     RETURN(result); 
    END$$ 
    DELIMITER ; 

如果你在一個名爲TEST.SQL文件保存上面的代碼,你可以通過執行以下運行MySQL提示 -

source test.sql; 
select test(0); 

它產生的輸出 -

+-----------------------------+ 
| test(0)      | 
+-----------------------------+ 
| 0.0000339946499848118900000 | 
+-----------------------------+ 
1 row in set (0.00 sec) 

正如你所看到的,數量越來越在第20位四捨五入,再用5個零被添加到它來獲得所要求的/指定的精密度。這是作弊。

是我錯了,或者是文檔錯了嗎?

+2

+1。 。 。我已經驗證過,即使使用'cast(0.0000339946499848118887'爲十進制(60,25))'也是如此。我認爲這個問題可能是浮點常量,但它也發生在字符串到十進制轉換之間。 –

+0

更新:我發現,在聲明DECIMAL(M,D)時,當D> 30時,MySQL返回一個錯誤。我找不到官方文件,但我認爲30是D的限制。但上述發現也與此相矛盾。 – Soumendra

+0

@GordonLinoff:我不太瞭解SQL,但在mysql shell中,語句'select cast('0.0000339946499848118887'爲十進制(60,25));'返回'0.0000339946499848118887000'正如預期的那樣。你看到了什麼? – ShreevatsaR

回答

2

我不知道SQL什麼,但我的猜測是這條線:

SET result = 0.339946499848118887e-4; 

如果MySQL是像我知道的,那麼這將首先評估右側其他語言的任何東西, 然後值分配給result。無論是聲明什麼類型result是,或者它宣佈什麼精度有,如果被評估時,右側已經失去了它的精度也沒有什麼關係。這幾乎肯定會發生在這裏。

我可以重現你的結果,但如果我把上面一行

​​

(從一個字符串從不確定精度浮點常數鑄件代替),然後我正確地得到

+-----------------------------+ 
| test(0)      | 
+-----------------------------+ 
| 0.0000339946499848118887000 | 
+-----------------------------+ 
1 row in set (0.00 sec) 
根據需要可以使用

。所以這是你的修復。


順便說一句,在該文檔中scaleDECIMAL(precision, scale)不能大於30似乎是在部分12.19.2. DECIMAL Data Type Changes

用於DECIMAL列中的聲明語法是DECIMAL(M,d)。是用於在MySQL 5.6的參數值的範圍 如下:

M是數字的最大數(精度)。它的範圍爲1 至65.(舊版本的MySQL允許範圍爲1至254.)

D是小數點右邊的數字位數( 比例)。它的範圍爲0到30,不得大於M.

+1

哦,我想我的'鑄造'和'小數'也可以是大寫。但我不明白爲什麼在慣用的SQL中有這麼多的吶喊。 :-) – ShreevatsaR

+0

照亮答案,謝謝。 – Soumendra

+0

Anshul在下面的答案闡明瞭MySQL根據它們的寫法對數字進行不同的處理! – Soumendra

3

這是因爲MySQL的對待0.339946499848118887e-4float和治療0.0000339946499848118887fixed point

mysql> select cast( 0.339946499848118887e-4 as DECIMAL(30, 25)); 
+----------------------------------------------------+ 
| cast( 0.339946499848118887e-4 as DECIMAL(30, 25)) | 
+----------------------------------------------------+ 
|      0.0000339946499848118900000 | 
+----------------------------------------------------+ 
1 row in set (0.00 sec) 

mysql> select cast( 0.0000339946499848118887 as DECIMAL(30, 25)); 
+-----------------------------------------------------+ 
| cast( 0.0000339946499848118887 as DECIMAL(30, 25)) | 
+-----------------------------------------------------+ 
|       0.0000339946499848118887000 | 
+-----------------------------------------------------+ 
1 row in set (0.00 sec) 

作爲上precision math - expression handling MySQL的文檔中描述 -

如果任何近似值存在時,表達式是近似的,並且使用浮點算術進行評價。

從,對文檔的numerical types報價,

兩個數字看起來很相似,可以區別對待。例如,2.34是精確值(定點)數字,而2.34E0是近似值(浮點)數字。

+0

我認爲這兩個答案都可能是正確的答案。不得不拋硬幣選擇其中之一!照亮答案,謝謝。 – Soumendra

相關問題