2015-06-09 3 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'. Результат операции modulo не может быть больше, чем divisor. – Nicolai

+1

Это базовая модульная арифметика, и я ожидаю правильный ответ ... и я даже показал правильный ответ; Я просто не уверен, что это самый эффективный способ сделать это. – tlum

ответ

2

MySQL не дает вам фиктивного результата, он просто использует другую реализацию модуля, чем вы ожидаете. К сожалению, термин модуль, по-видимому, определен несколько неоднозначно, и его реализация варьируется от языка к языку. Из того, что я могу сказать в Wikipedia on Modulo, реализация в MySQL использует усеченного деление:

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

Где вы ждете реализаций использовать этажное подразделение:

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

С это, как вы применили свой первый способ обхода, я бы сказал, что это, вероятно, лучшая альтернатива оператору .

Из того, что я видел (и это очень быстрый ненаучный анализ!), Кажется, более императивные языки программирования реализовать усеченный деление и более функциональные математические языки, кажется, используют сражен деление.

+0

MySQL дает математически неправильное решение проблемы; это связано с тем, что усеченное деление ошибочно. Евклидовые теоремы датируются более 2000 лет назад. Сегодня калькуляторы пытаются уловить суть этого, используя современные теоретики в области информатики, но некоторые реализации выполняют более полную работу, чем другие. «Несмотря на широко распространенное использование, усеченное деление, как оказалось, уступает другим определениям». --Лейен, Даан (3 декабря 2001 г.). [«Отдел и модуль для компьютерных ученых»] (http://research.microsoft.com/pubs/151917/divmodnote.pdf) Retrieved 2015-06-09. – tlum

Смежные вопросы