2009-11-19 3 views
1

Внутренне, что происходит с представлением с плавающей запятой справа, чтобы получить значение false?Ошибка округления с плавающей точкой MySQL

mysql> SELECT 3.1415 + 0.9585 = 4.1, 3.1415E0 + 0.9585E0 = 4.1E0; 
+-----------------------+-----------------------------+ 
| 3.1415 + 0.9585 = 4.1 | 3.1415E0 + 0.9585E0 = 4.1E0 | 
+-----------------------+-----------------------------+ 
|      1 |       0 | 
+-----------------------+-----------------------------+ 

редактировать Вывод: Не используйте Float или Double для точной математики. Используйте десятичный знак.

+1

Не используйте поплавки для абсолютной математики. –

+0

Перед тем, как разрешить оставлять вопрос, должна пройти обязательная викторина с плавающей точкой. – recursive

+2

Их называют «поплавками», потому что тела программистов, которые используют их там, где требуется точность, часто обнаруживаются в гавани после того, как приложение переходит в производство. –

ответ

2

Прежде всего, вы должны never use = с плавающими точками, поскольку вы просто не можете предсказать, не возникнут ли ошибки округления. Всегда используйте < или>, в зависимости от того, чего вы хотите достичь.

Во-вторых: Ничего плохого в любой формуле. Внутри оба варианта кодируются в своих переменных до ближайшего возможного двоичного представления, которое немного отличается от установленного вами значения.

Одна цифра перед десятичной точкой является стандартной, поэтому используются все следующие цифры. С правой стороны вы конкретно определяете, где находится запятая, тем самым «тратя» определенную часть в конце двоичного представления вашей переменной, что приводит к ошибкам округления (в данном конкретном случае).

1

плавающие точки, такие как FLOAT или DOUBLE, всегда являются неподходящими, потому что они являются приблизительными, а не точными значениями, вы не должны использовать их для расчетов. Вместо этого используйте тип данных DECIMAL.

+1

Однако допустимые действия для FLOAT, которые не могут быть удовлетворены DECIMAL. – ty812

1

MySQL, так же, как практически любая реализация компьютера, использующая арифметику с плавающей запятой, использует IEEE-754 standard. Это двоичная с плавающей запятой.

Так же, как невозможно записать 1/3 в десятичном значении, невозможно записать бесконечно много цифр в двоичной плавающей запятой (учитывая, что компьютеры ограничены во времени и пространстве). Поплавок использует 32 бита, двойной использует 64 бита, математически, это очень мало места для бесконечных многих фракций.

Статья в Википедии, прочитанная выше о плавающей запятой. В целом, имея дело с компьютерным совпадением, необходимо знать, как компьютеры используют ограниченное хранилище для неограниченных фракций.

Точные десятичные знаки также существуют, но ограничены фиксированным диапазоном (то есть нет высокого показателя). В MySQL вы можете использовать DECIMAL для чисел с фиксированной точкой.

0

В этом, повезло, что первые один по сравнению точно:

SELECT 3.1415 + 0.9585 = 4.1, 3.1415E0 + 0.9585E0 = 4.1E0; 

Тестовые плавающих точек для около равенства таким образом:

mysql> SELECT abs(3.1415 + 0.9585 - 4.1) < 0.0001, abs(3.1415E0 + 0.9585E0 - 4.1E0) < 0.0001; 
+-------------------------------------+-------------------------------------------+ 
| abs(3.1415 + 0.9585 - 4.1) < 0.0001 | abs(3.1415E0 + 0.9585E0 - 4.1E0) < 0.0001 | 
+-------------------------------------+-------------------------------------------+ 
|         1 |           1 | 
+-------------------------------------+-------------------------------------------+ 
1 row in set (0.00 sec) 

Выберите разницу (где я использовал 0,0001) соответствующим значениям.

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