Почему усечение MySQL с плавающей точкой 6.099999904632568 в 6.1 - PullRequest
0 голосов
/ 16 сентября 2018

Я понимаю, что float - это приближение, которое зависит от точности, которую вы хотите. Однако я не совсем понимаю, почему он конвертирует 6.099999904632568 в 6.1. Почему нужно округлять его, а не останавливаться с максимальной точностью (т. Е. 6.09999990)

В любом случае, я могу заставить число храниться с максимальной точностью без округления?

Таблица информации

CREATE TABLE `urls` ( `id` int(11) NOT NULL AUTO_INCREMENT, `gcloud_magnitude` float DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1193 DEFAULT CHARSET=utf8;

Код для воспроизведения

mysql> INSERT INTO urls (url_md5, gcloud_magnitude, created_at, updated_at) VALUES ('noop', 6.099999904632568, '2018-09-16 14:57:49', '2018-09-16 14:57:49'); Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM urls WHERE url_md5 = 'noop'\G; id: 1193 url_md5: noop gcloud_magnitude: 6.1 1 row in set (0.00 sec)

интерпретатор Ruby разбирает как float

irb(main):004:0> Url.find_by(url_md5: 'noop').gcloud_magnitude.to_f => 6.1

Ответы [ 3 ]

0 голосов
/ 17 сентября 2018

Значение, которое вы видите, 6.1, вероятно, является так называемым roundtrip output.Это самый короткий вывод, который при разборе вернет то же значение, что и .Не во всех языках выводится число с плавающей запятой или удваивается как в оба конца, но некоторые делают, если явно не указано иное.Я предполагаю, что Ruby является одним из них.

Значение 6.1, когда анализируется как float, получает точное значение 6.099999904632568359375, но значение 6.099999904632568, когда анализируется, получает точно такое же значение.6.1 является кратчайшим выходным сигналом, который может быть сгенерирован для данного конкретного числа с плавающей запятой, и при повторном чтении (повторном анализе) он сгенерирует тот же самый тип с плавающей запятой.

0 голосов
/ 18 сентября 2018

Я хотел бы обобщить свои выводы в качестве ответа.

Когда я сохраняю значение, такое как 6.099999904632568, в тип данных с плавающей запятой, MySQL представляет его как 6.1.Когда я изменяю тип данных на decimal with precision 64 and scale 30, автоматически появляется 6.099999904632568 без моего обновления значения.

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

Это сбивает с толку меня.Если MySQL знает исходное представление, почему я не могу извлечь исходное значение без его преобразования в тип с плавающей запятой.Кроме того, поскольку 6.099999904632568 имеет более высокую точность, чем то, что могут обрабатывать 4 байта, как он хранит исходное представление?

Больше вопросов, не связанных с этим исходным вопросом.

0 голосов
/ 16 сентября 2018

Тип данных FLOAT в MySQL не обладает достаточной точностью для хранения заданного вами значения.Тип данных DOUBLE может сделать это.

Пример:

mysql> create table f ( f float, d double);

mysql> insert into f values (6.099999904632568, 6.099999904632568);

mysql> select * from f;
+------+-------------------+
| f    | d                 |
+------+-------------------+
|  6.1 | 6.099999904632568 |
+------+-------------------+

FLOAT округляет значение до точности, которую оно может сохранить.Фактически, округление происходит даже со значениями с меньшей точностью, чем используемое вами значение.

mysql> select * from f;
+---------+-------------------+
| f       | d                 |
+---------+-------------------+
|     6.1 | 6.099999904632568 |
|     6.1 |         6.0999999 |
|     6.1 |          6.099999 |
| 6.09999 |           6.09999 |
+---------+-------------------+

В 32-битном FLOAT битов недостаточно для сохранения неограниченной точности.Таким образом, оно должно округлять значение.

Вы также обнаружите, что есть предел точности DOUBLE.Хранит значения в 64-битном формате.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...