Переменная BigDecimal, дополненная случайными числами в JDBC Insert - PullRequest
1 голос
/ 22 февраля 2011

Рассмотрим оператор SQL INSERT INTO table (field) VALUES (-0.11111111) с field Тип Oracle NUMBER.

Если значение для вставки имеет тип float или double, вы получите точное значение в field, то есть -0,11111111.

Но когда значение для вставки имеет тип BigDecimal, вы получаете значение, дополненное случайными числами, то есть 0,1111111099999999990428634077943570446223.

Почему?

Java заявляет, что «BigDecimal является неизменяемым десятичным числом со знаком произвольной точности».

Код:

String sql = "INSERT INTO pat_statistics (file_key,test_number,rqw)"
    + " VALUES (3778, 100, " + new BigDecimal(-0.11111111) + ")";
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, user, pwd);
Statement st = conn.createStatement();
int n = st.executeUpdate(sql);

БД - это Oracle.

Ответы [ 2 ]

4 голосов
/ 22 февраля 2011

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

Я предполагаю, что вы видите эту базу данных, потому что драйвер jdbc думает: Эй, я получаю BigDecimal. Я могу использовать все цифры, которые могу освоить.

Когда вы используете float или double, драйвер jdbc знает, что я не могу полагаться на все цифры, и игнорирует то, что следует после этого порога.

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

=== другое исправление ====

Обработка выполняется не драйвером jdbc, а различными преобразованиями toString, поскольку вы собираете строку SQL.

Кстати: для этого вам действительно следует использовать переменные связывания.

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

Для литерального значения вы всегда должны использовать конструктор BigDecimal, принимающий строковый аргумент. Подробности смотрите в документации конструктора BigDecimal (double) .

...