Представление десятичных чисел с MySQL тип с плавающей точкой? - PullRequest
1 голос
/ 28 июля 2011

Я знаю, что это плохая идея хранить десятичные значения как float в mysql.

Пример. Если я храню товар по цене 5,01 доллара, точного представления этого числа с плавающим типом не существует.

Если я это сделаю:

CREATE TABLE IF NOT EXISTS `test` (
  `test` float NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

INSERT INTO `test` (`test`) VALUES
(5.01);

и затем вы запускаете запрос

SELECT AVG( test ) 
FROM test

против этой таблицы вы получите:

mysql> select avg(test) from test;
+------------------+
| avg(test)        |
+------------------+
| 5.01000022888184 |
+------------------+
1 row in set (0.00 sec)

однако, если вы выберете только поле, подобное этому:

mysql> select * from test;
+------+
| test |
+------+
| 5.01 |
+------+
1 row in set (0.00 sec)

вы получите правильную сумму.

Мой вопрос: как это может быть?

Если тип с плавающей запятой не может точно представлять мое значение?

Разве выбор не должен возвращать 5.01000022888184?

Ответы [ 3 ]

1 голос
/ 28 июля 2011

Причина, по которой простой выбор возвращает 5,01, заключается в том, что это самое короткое число, которое ближе к фактическому значению, чем к любому другому числу с плавающей запятой; MySQL отображает это вместо преобразования действительного значения обратно в ближайшую десятичную дробь, потому что в большинстве случаев пользователи воспримут этот результат как «более правильный».

Причина, по которой avg() ведет себя по-разному, заключается, вероятно, в том, что он выполняет свои вычисления, используя double, а 5.01, конечно, не ближе к фактическому значению с округлением до float, чем все double значений, потому что их гораздо больше.

1 голос
/ 28 июля 2011

Я думаю, что это так же просто, как в БД хранит число, как и, однако, как только вы им манипулируете, оно затем используется в форме IEEE 754

см. Предыдущий (связанный с оракулом) вопрос OracleПоплавки против числа

0 голосов
/ 18 октября 2012

Реальная проблема в том, что вы не можете сделать:

SELECT * FROM `test` WHERE `test` = 5.01

Значение с плавающей запятой, хранимое в MySQL, равно непознаваемое

Это огромная ошибка, но они не хотят ее исправлять. Десятичные и двойные имеют похожие проблемы. Единственное исправление - указать точную точность для поля в вашей схеме

ALTER TABLE `test` change `test` `test` FLOAT(10,2)

Но тогда вы теряете любую точность в расчете, где точность будет меньше указанной (например, любые дроби)

...