Точность десятичного деления T-SQL - PullRequest
21 голосов
/ 08 января 2009

Кто-нибудь знает почему, используя 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

Ответы [ 6 ]

28 голосов
/ 08 января 2009

Для умножения мы просто складываем количество десятичных разрядов в каждом аргументе вместе (используя ручку и бумагу), чтобы получить выходные десятичные разряды.

Но дивизия просто разрывает голову. Я сейчас ложусь.

В терминах 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,99900000
  • 146804871.212533000000000 и 12499999,99900000000000
14 голосов
/ 03 апреля 2009

Короче говоря, используйте DECIMAL (25,13), и вы будете в порядке со всеми вычислениями - вы получите точность, как заявлено: 12 цифр до десятичной точки и 13 десятичных после. Правило: p + s должно равняться 38, и вы будете в безопасности! Почему это? Из-за очень плохой реализации арифметики в SQL Server! Пока они не исправят это, следуйте этому правилу.

10 голосов
/ 07 декабря 2009

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

select 49/30                   (result = 1)

станет:

select 49/cast(30 as float)    (result = 1.63333333333333)
4 голосов
/ 08 октября 2010

Мы ломали голову над магическим переходом,

P & S связаны, поэтому:

  1. (72,54) -> (38,29)

  2. (84,54) -> (38,8)

Предполагая, что (38,29) является опечаткой и должно быть (38,20), математика следующая:

  1. я. 72 - 38 = 34, II. 54 - 34 = 20

  2. я. 84 - 58 = 46, II. 54 - 46 = 8

И это рассуждение:

я. Точность вывода меньше максимальной точности - это цифры, которые мы собираемся выбросить.

* 1 034 * II. Тогда выходной масштаб меньше того, что мы собираемся выбросить, дает нам ... оставшиеся цифры в выходном масштабе.

Надеюсь, это поможет кому-то еще, пытающемуся понять это.

3 голосов
/ 08 января 2009

Преобразуйте выражение, а не аргументы.

select  CONVERT(DECIMAL(38,36),146804871.212533 / 12499999.9999)
0 голосов
/ 16 марта 2017

ВЫБЕРИТЕ COL1 * 1.0 / COL2

Это может помочь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...