1.2 в базе данных SQLite3 на самом деле 1.199999998 - PullRequest
0 голосов
/ 25 февраля 2011

Я пытаюсь сохранить число с плавающей точкой в ​​моей базе данных SQLite3, используя Java. Когда я иду, чтобы сохранить число 1.2 в базе данных, оно фактически сохраняется как 1.199999998, и то же самое происходит для каждого четного числа (1.4, 1.6 и т. Д.).

Это действительно затрудняет удаление строк, потому что я удаляю строку в соответствии со столбцом ее версии (тип = float). Так что эта строка не будет работать: "УДАЛИТЬ ИЗ ТАБЛ. ГДЕ версия = 1.2"

Это потому, что нет 1.2, а только 1.19999998. Как я могу убедиться, что при сохранении числа с плавающей запятой в моей базе данных SQLite3, это именно то число, которое я ввел?

Ответы [ 5 ]

3 голосов
/ 25 февраля 2011

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

2 голосов
/ 25 февраля 2011

Помните, что 1.2, который вы указали в своем исходном коде или что пользователь ввел текстовое поле и в конечном итоге попал в базу данных, фактически хранится в виде двоичного значения (обычно в формате, известном как IEEE754). Чтобы понять, почему это проблема, попробуйте вручную преобразовать 1.2 (1 1/5) в двоичный файл (двоичный .1 равен 1/2, .01 - 1/4) и посмотрите, что у вас получится:

1.001100110011001100110011001100110011

Вы можете сэкономить время, используя этот конвертер (игнорируйте последнюю "1", которая прерывает цикл на сайте & mdash; ее потому, что конвертер должен был округлить последнюю цифру).

Как видите, это повторяющийся паттерн. Это продолжается почти всегда. Это все равно что пытаться представить 1/3 в виде десятичной дроби. Чтобы обойти эту проблему, большинство языков программирования имеют десятичный тип (в отличие от float или double), который поддерживает представление 10. Однако вычисления, выполняемые с использованием этого типа, на несколько порядков медленнее, и поэтому обычно они зарезервированы для финансовых транзакций и т. П.

1 голос
/ 25 февраля 2011

Как отметил Джоэл Коухорн, 1.2 - это повторяющаяся дробь 1.0011 0011 0011 ... в двоичном формате и не может быть точно представлена ​​в конечном количестве битов.

Самое близкое, что вы можете получить с IEEE 754 float, это 1.2000000476837158203125. Самое близкое, что вы можете получить с double, это 1.1999999999999999555910790149937383830547332763671875. Я не знаю, откуда вы получаете 1.199999998.

Плавающая точка была разработана для представления приблизительных величин: физических измерений (плавательный бассейн никогда не бывает точно 1,2 метра глубиной) или иррациональных функций, таких как sqrt, log или sin. Если вам нужно значение с точностью до 15 значащих цифр, оно работает нормально. Если вам действительно нужно точное значение, не так уж и много.

Для номера версии более подходящим представлением будет пара целых чисел: одно для основной версии и одно для вспомогательной версии. Это также правильно обрабатывает последовательность 1.0, 1.1, ..., 1.9, 1.10, 1.11, которая неправильно сортирует в столбце REAL.

1 голос
/ 25 февраля 2011

Вы никогда не должны полагаться на точность с плавающей или двойной.Поплавок никогда не должен использоваться для ключей в базе данных или для представления денег.

В этом случае вам, вероятно, следует использовать десятичную дробь.

Плавания не являются точным типом данных.Они предназначены для быстрой работы, имеют большой диапазон значений и занимают мало места в памяти.

Они обычно реализуются с использованием стандарта IEEE

http://en.wikipedia.org/wiki/IEEE_754-2008

1 голос
/ 25 февраля 2011

Это сама природа чисел с плавающей точкой. Они не точны. Я бы посоветовал вам использовать целое число или текстовое поле для хранения версии.

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