Я использую SQL Server 2012
SELECT
0.15 * 30 / 360,
0.15 / 360 * 30
Результаты:
0.012500,
0.012480
Это даже сбивает меня с толку:
DECLARE @N INT = 360
DECLARE @I DECIMAL(38,26) = 0.15 * 30 / 360
DECLARE @C DECIMAL(38,26) = 1000000
SELECT @C * @I * POWER(1 + @I, @N) / ( POWER(1 + @I, @N) - 1 )
SELECT @C * (@I * POWER(1 + @I, @N) / ( POWER(1 + @I, @N) - 1 ) )
Первый выбор дает мне правильный результат: 12644.44022 Второй выбор усекает результат: 12644.00000
sql-server
sql-server-2012
t-sql
decimal
cpacheco
источник
источник
Ответы:
Определение точности и масштаба в результате выражений - это крысиное гнездо, и я не думаю, что кто-то понимает точные правила в каждом сценарии, особенно при смешивании десятичных (или плавающих!) И целых чисел. Смотрите этот ответ от gbn .
Вы можете, конечно, адаптировать выражения, чтобы дать вам то, что вы хотите, делая гораздо более подробные явные преобразования. Это, вероятно, излишне, но:
Ни один из результатов не округляется неправильно из-за неработающей математики с плавающей запятой или дико неверной точности / шкалы.
источник
Как отметил Аарон Бертран, выражения очень сложно предсказать.
Если вы решитесь пойти туда, вы можете попытаться получить представление, используя следующий фрагмент:
Это результат:
источник
Несмотря на прекрасные ответы, уже добавленные к этому вопросу, существует явно определенный порядок приоритета для преобразования типов данных в SQL Server.
Когда оператор объединяет два выражения разных типов данных, правила для приоритета типа данных указывают, что тип данных с более низким приоритетом преобразуется в тип данных с более высоким приоритетом. Если преобразование не поддерживается неявным преобразованием, возвращается ошибка. Если оба выражения операнда имеют один и тот же тип данных, результат операции имеет этот тип данных.
SQL Server использует следующий порядок приоритета для типов данных:
Так, например, если вы
SELECT 0.5 * 1
(умножая десятичное число на целое число) вы получите результат, который преобразуется в десятичное значение, такdecimal
как приоритет выше, чем уint
типа данных.См. Http://msdn.microsoft.com/en-us/library/ms190309.aspx для получения дополнительной информации.
Сказав все это, вероятно ,
SELECT @C * (@I * POWER(1 + @I, @N) / (POWER(1 + @I, @N) - 1 ));
должно вернуть десятичное значение, так как практически все входные данные являются десятичными. Интересно, что вы можете принудительно изменить результат, изменив егоSELECT
на:Это возвращает:
Я затрудняюсь объяснить, как это имеет какое-то значение, хотя, очевидно, это имеет значение . Я предполагаю , что
1E0
(явное значение с плавающей точкой) вPOWER(
функции заставляет SQL Server сделать другой выбор типов вывода дляPOWER
функции. Если мое предположение верно, это указывало бы на возможную ошибку вPOWER
функции, поскольку в документации указано, что первым вводомPOWER()
является число с плавающей точкой или число, которое можно неявно преобразовать в число с плавающей точкой.источник
Вы знакомы с
SELECT .. INTO
синтаксисом ? Это полезный трюк для деконструкции подобных ситуаций, потому что он создает на лету таблицу с правильными типами данных для данногоSELECT
списка.Вы можете разбить свой расчет на составляющие его этапы, применяя правила приоритета SQL Server по мере необходимости, чтобы увидеть, как меняется определение. Вот как будет выглядеть ваш первый пример:
Это вывод:
источник
(1+1)
и2
имеют тип,int
но у этого вопроса есть пример, где они заканчивают тем, что приводили к другому типу результата.