Точность десятичного деления T-SQL
Кто-нибудь знает, почему, используя SQLServer 2005
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,9),12499999.9999)
дает мне 11.74438969709659,
но когда я увеличиваю десятичные знаки на знаменателе до 15, я получаю менее точный ответ:
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,15),12499999.9999)
дайте мне 11.74438969
Ответы
Ответ 1
Для умножения мы просто добавляем число десятичных знаков в каждом аргументе вместе (используя ручку и бумагу), чтобы выработать выходные места dec.
Но деление просто размахивает головой. Я сейчас лечу.
В SQL-выражениях, однако, точно так, как ожидалось.
--Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
--Scale = max(6, s1 + p2 + 1)
--Scale = 15 + 38 + 1 = 54
--Precision = 30 - 15 + 9 + 54 = 72
--Max P = 38, P & S are linked, so (72,54) -> (38,20)
--So, we have 38,20 output (but we don use 20 d.p. for this sum) = 11.74438969709659
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,9),12499999.9999)
--Scale = 15 + 38 + 1 = 54
--Precision = 30 - 15 + 15 + 54 = 84
--Max P = 38, P & S are linked, so (84,54) -> (38,8)
--So, we have 38,8 output = 11.74438969
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,15),12499999.9999)
Вы можете выполнить ту же математику, если следуете это правило, если вы рассматриваете каждую пару чисел как
- 146804871.212533000000000 и 12499999.999900000
- 146804871.212533000000000 и 12499999.999900000000000
Ответ 2
Короче говоря, используйте DECIMAL (25,13), и все будет хорошо со всеми вычислениями - вы получите точность, как указано: 12 цифр до десятичной точки и 13 десятичных цифр после.
Правило: p + s должно равняться 38, и вы будете в безопасности!
Почему это?
Из-за очень плохой реализации арифметики в SQL Server!
Пока они не исправят это, следуйте этому правилу.
Ответ 3
Я заметил, что если вы разделили разделительное значение на float, он даст правильный ответ, т.е.:
select 49/30 (result = 1)
станет:
select 49/cast(30 as float) (result = 1.63333333333333)
Ответ 4
Мы были озадачены магическим переходом,
P и S связаны, поэтому:
-
(72,54) → (38,29)
-
(84,54) → (38,8)
Предполагая, что (38,29)
является опечаткой и должно быть (38,20)
, следующая математика:
-
я. 72 - 38 = 34,
II. 54 - 34 = 20
-
я. 84 - 58 = 46,
II. 54 - 46 = 8
И это рассуждение:
я. Точность вывода меньше максимальной точности - это цифры, которые мы собираемся выбросить.
II. Тогда масштаб вывода меньше, чем мы собираемся выбросить, дает нам... оставшиеся цифры в выходной шкале.
Надеюсь, это поможет кому-то еще попытаться понять это.
Ответ 5
Преобразуйте выражение, а не аргументы.
select CONVERT(DECIMAL(38,36),146804871.212533 / 12499999.9999)
Ответ 6
Использование следующего может помочь:
SELECT COL1 * 1.0 / COL2