2013-02-20 2 views
1

У меня проблема при вводе двойного значения в таблицу базы данных с некоторой десятичной точностью. Я использую MS SQL Server версии 10.0.4000 Ниже приведен пример таблицы с десятичным столбцом с 4 знаками после запятой.Десятичное усечение/округление разницы в консоли и хотя JDBC

create table test (
test decimal (18,4)) 

Когда я ввожу значение «36.78675» через консоль MSSQL, он получает закруглены 36.7868 как поле имеет только 4 знака после запятой. Это отлично.

DECLARE @T DECIMAL(18, 5) 

SET @T = 36.78675 

insert into test values(@T) 

select * from test 

Но когда я выполнить эквивалентную вставку (с использованием подготовленного оператора) через мой код Java (драйвер JDBC MS SQL), данные получает хранится в таблице 36.7867. Если у меня есть значение как 36.786750001, то и консоль, и раунды JDBC до 36.7868. Объект java, который я использую, является двойным. Я вызываю setDouble() с двойным значением. Здесь он автоматически выбирает тип данных. Но есть еще один метод JDBC, который принимает объект и тип данных. Используя это, я тестировал с типом DECIMAL и FLOAT. Все дают тот же результат. Я даже изменил драйвер jdbc на I-net. Там тоже такой же результат.

Кто-нибудь знает, почему округление работает по-разному через водителя? Есть ли какие-либо настройки, чтобы заставить его вести себя как консоль?

+0

Говоря «Консоль SQL Server», вы имеете в виду SQL Server Management Studio? – abatishchev

+0

@abatishchev Да –

ответ

4

Это из-за природы двоичной с плавающей запятой, с которой вы работаете с double (на Java).

точное значение double ближайшего к 36.7875 является

36.7867499999999978399500832892954349517822265625 

Это будет округлена до 36.7867. В то время как точное значение double ближайшего к 36.78750001 является

36.786750000099999624580959789454936981201171875 

Это будет округлена до 36.7878. Вот почему вы получаете такое поведение. Консоль, по-видимому, обрабатывает вход как десятичное число вместо того, чтобы конвертировать в двоичную с плавающей запятой вообще.

Если для вас важны точные десятичные цифры, вы, вероятно, не должны использовать двоичный тип с плавающей запятой - вместо этого используйте BigDecimal.

Вы действительно должны думать о том, что представляет ваша ценность. Если это физическое непрерывное значение, такое как высота, длина или вес, то использование double, вероятно, подходит в конце концов - но вы не должны зависеть от таких случаев. Если это искусственная конструкция с дискретными (десятичными) значениями, такими как денежные значения, то вы должны обязательно использовать BigDecimal или просто масштабировать целое число.

+0

Спасибо за детали. Моя проблема заключается в несогласованности в java rouding и усечении/округлении базы данных по умолчанию. Java rounding дает 36.7868, когда значение «36.78675», но хранимое значение в datatbase равно «36.7867», если оно не имеет значения для округления значения перед хранением. Мне нужно восстановить данные и выполнить сравнение со значением в java-коде. Здесь я не получу совпадение, сравнивая 36.7868 (java-код) с 36.7867 (databse). –

+2

@BijuSanakan: Я хочу сказать, что значение переменной 'double' * не может быть 36.78675.Это просто невозможно. Это похоже на попытку записать точное значение «одна треть» в десятичном представлении. Опять же, если точное значение «36.78675» важно для вас, вы должны использовать «BigDecimal». –

+0

Я согласен с вами. Но мой вопрос в том, почему он по-разному округляется в java и mssql для того же числа 36.78675. государственной статической силы roundUnits (двойной v1) { возвращение java.util.Math.round (v1 * 10000)/10000; double d = 36.78675; System.out.println (roundUnits (d)); Когда я вызываю вышеуказанный код, он печатает 36.7868. Я ожидаю такого же поведения от MSSQL. Но в MSSQL он хранится как 36.7867 –

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