2015-06-09 62 views
1

至少在MySQL v5.1.73(CentOS 6.6)中,MOD()函數返回一個僞造的結果......除非有人能夠解釋這實際上是正確的。MySQL MOD()已損壞:這是最好的選擇嗎?

mysql> select MOD(-385.4784399 ,1440); 
+-------------------------+ 
| MOD(-385.4784399 ,1440) | 
+-------------------------+ 
|   -385.4784399 | 
+-------------------------+ 
1 row in set (0.01 sec) 

這是最好的選擇?

mysql> select -385.478439885319 - 1440 * FLOOR(-385.478439885319/1440); 
+----------------------------------------------------------+ 
| -385.478439885319 - 1440 * FLOOR(-385.478439885319/1440) | 
+----------------------------------------------------------+ 
|          1054.521560114681 | 
+----------------------------------------------------------+ 
1 row in set (0.00 sec) 

我認爲這樣也會起作用,但是要做一些簡單的事情還需要很長時間。

mysql> select MOD((MOD(-385.478439885319, 1440) + 1440), 1440); 
+--------------------------------------------------+ 
| MOD((MOD(-385.478439885319, 1440) + 1440), 1440) | 
+--------------------------------------------------+ 
|        1054.521560114681 | 
+--------------------------------------------------+ 
1 row in set (0.00 sec) 
+0

它不會被破壞,除非有一些說明你可以指出它不符合要求。它在文檔中被定義爲一個餘數,沒有例子給出負的第一個參數。 – EJP

+0

你期望什麼結果? MOD是模運算,並返回'-385.478439885319'除以'1440'的餘數。模運算的結果不能大於除數。 – Nicolai

+1

這是基本的模塊化算術,我期待正確的答案......我甚至展示了正確的答案;我只是不確定這是最有效的方法。 – tlum

回答

2

MySQL不會給你一個假結果,它只是使用不同的模數實現,而不是你所期望的。不幸的是,術語模數似乎已經被模糊地定義了,實現因語言而異。從我可以在Wikipedia on Modulo告訴,MySQL的實現方案是採用截斷師

r = a - n * trunc(a/n)

如果你期望的實現,以使用地板師

r = a - n * floor(a/n)

由於這是如何實施您的第一個解決方法,我想說這可能是Mod運營商的最佳選擇。

從我已經看到了(這是一個非常快的不科學分析!),這似乎是更爲迫切的編程語言實現截斷師和功能更強大的數學語言似乎使用地板師

+0

MySQL給這個問題提供了一個數學上不正確的解決方案;這是因爲截斷分裂是有缺陷的。歐幾里德定理可以追溯到2000多年前。今天,計算器試圖用現代計算機科學定理來捕捉它的本質,但是一些實現比其他實現做得更完整。 「儘管它被廣泛使用,截斷的分割被證明不如其他定義。」 - 大安,Leijen(2001年12月3日)。 [「計算機科學家的分工和模數」](http://research.microsoft.com/pubs/151917/divmodnote.pdf)檢索2015-06-09。 – tlum