2012-02-13 4 views
4

Я пытаюсь сделать раунд в sql, но результат очень странный; Вот что я делаю:sql округление не всегда округляет

Я использую MSSQL

У меня есть выбор:

Select num1, num2, num1 * num2, round(num1 * num2, 2) 
from myTable 

Datatype:

num1 поплавковый

num2 является деньги

если значение num1 составляет 15 и значение num2 является 0,033 Вот мой ResultSet:

15, 0,033, 0,495, 0,5

Проблема заключается в том, когда у меня есть эти значения :

если значение num1 5 и значение num2 является 0,045 Вот мой ResultSet:

5, 0.045, 0.225, 0.22

У кого-то есть идея?

+1

Вы абсолютно уверены, что должны использовать тип данных MONEY? Есть довольно убедительная запись о том, почему этого следует избегать, если это вообще возможно, в пользу десятичного числа здесь: http://sqlserverpedia.com/blog/sql-server-bloggers/throw-your-money-away/ – David

+0

I ' Я попробовал это в своем sqlect: round (convert (decimal (10, 3), num2) * num1, 2) и он не работает :( – GregM

+0

Интересно ... это работает для меня ... попробуйте это: выберите round (CONVERT (десятичный (10,3), 0,045) * 5, 2). Только что: «select round (5 * 0.045, 2)» также дает правильный результат для меня. – David

ответ

0

Я конвертировал свою поплавковую колонку в деньги и, похоже, сейчас работает.

Спасибо всем!

+0

Вам следует избегать типа данных денег. Я бы настоятельно рекомендовал вам рассмотреть диапазон обоих значений и использовать соответствующие десятичные числа и понять правила десятичного масштаба и точности и принять правильное решение относительно того, что делать с дробными копейками. Кроме того, насколько мне известно, никогда не имеет смысла умножать два типа денег - у вас никогда не было $ x $ y - для получения денег, только для того, чтобы разделить, чтобы получить скаляр. В итоге вы получите x * y $^2 - нет такой вещи, как квадратный доллар, например, квадратный фут или кубический метр или что-то еще. –

1

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

+0

Жаль, что я использую mssql, я отредактировал свой вопрос, я не думаю, что долго существует в mssql – GregM

+1

никогда не используйте float, если хотите точную математику. Используйте десятичный тип. – HLGEM

0

Какую версию SQL вы используете?

Попробуйте этот код в Query Analyzer


DECLARE @num1 float 
DECLARE @num2 money 

SET @num1 = 15 
SET @num2 = 0.033 

SELECT 
@Num1, 
@Num2, 
@Num1 * @Num2, 
ROUND(@Num1 * @Num2,0), 
ROUND(@Num1 * @Num2,1), 
ROUND(@Num1 * @Num2,2), 
ROUND(@Num1 * @Num2,3) 

Float является приближение не является вещественным числом. Вместо этого используйте Decimal.


DECLARE @num1 decimal 
DECLARE @num2 money 

SET @num1 = 5 
SET @num2 = 0.045 

SELECT 
@Num1, 
@Num2, 
@Num1 * @Num2, 
ROUND(@Num1 * @Num2,2), 
ROUND(CAST(@Num1 as money) * @Num2,2) 
+0

Извините, что я забыл, 2 в моей круглой функции, но этот вариант в порядке, вот результат: 15 \t 0.033 \t 0,495 0,5 \t 0,5 \t 0,495; Это мои другие данные, 5 и 0.045, которые дают мне проблемы – GregM

5

Если посмотреть на this runnable example в режиме просмотра сетки (обратите внимание также, что текстовый режим отличается), вы должны увидеть проблему:

DECLARE @tbl AS TABLE (num1 float, num2 money); 
INSERT INTO @tbl VALUES (15, 0.033), (5, 0.045); 

Select num1, num2, num1 * num2, round(num1 * num2, 2) 
from @tbl; 

Обратите внимание, что число на самом деле 0,224999999, которая округляет to .22 - вам нужно быть осторожным при просмотре недвоичного выхода SQL Server - он иногда преобразует числа в текст так, как вы этого не ожидаете.

Это происходит от операции с плавающей запятой, что приводит к поплавке, которое подвержено проблемам двоичного представления.

Вы должны подумать о том, что это означает для вашего значения с плавающей запятой, и подумайте об использовании десятичного числа и look at the rules for scale and precision for decimal operations. Обратите внимание, что деньги только несколько похожи на десятичные (19, 4)

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