Sql Server Precision Crazyness - PullRequest
       4

Sql Server Precision Crazyness

5 голосов
/ 17 ноября 2010

У меня проблема с точностью сервера sql.

У меня есть следующие запросы:

DECLARE @A numeric(30,10)
DECLARE @B numeric(30,10)
SET @A = 20.225
SET @B = 53.3875
SELECT @A * @B

DECLARE @A1 numeric(30,14)
DECLARE @B1 numeric(30,14)
SET @A1 = 20.225
SET @B1 = 53.3875
SELECT @A1 * @B1

DECLARE @A3 numeric(30,15)
DECLARE @B3 numeric(30,15)
SET @A3 = 20.225
SET @B3 = 53.3875
SELECT @A3 * @B3

DECLARE @A2 numeric(20,15)
DECLARE @B2 numeric(20,15)
SET @A2 = 20.225
SET @B2 = 53.3875
SELECT @A2 * @B2

DECLARE @A4 float
DECLARE @B4 float
SET @A4 = 20.225
SET @B4 = 53.3875
SELECT @A4 * @B4

Что дает следующие результаты соответственно:

1079,762188

1079,762188

1079,7621875

+1079,762187500000000000000000000

1079,7621875

Правильный ответ: 1079.7621875.

Я не понимаю, почему, когда типы имеют одинаковую сигнатуру, они теряют точность. Кроме того, почему переход с 30,14 на 30,15 решает проблему точности? Кроме того, почему 20,15 имеет гораздо больше десятичных знаков, чем 30,15?

Я прочитал эту статью http://msdn.microsoft.com/en-us/library/ms190476(SQL.90).aspx и думаю, что все будет в порядке, потому что мои переменные имеют одинаковую точность.

Любая помощь будет высоко ценится!

Ответы [ 2 ]

3 голосов
/ 17 ноября 2010

Это важно в нижней части вставленной ссылки:

  • Точность и масштаб результата имеют абсолютный максимум 38. Когда точность результата превышает 38,соответствующая шкала уменьшена, чтобы предотвратить усечение неотъемлемой части результата.

Для всех результатов с точностью до 30 результирующая вычисленная точность равна 61. Посколькумаксимально возможная точность равна 38, результирующая точность уменьшается на 23. Таким образом, все шкалы также уменьшаются, чтобы избежать усечения неотъемлемых частей результата больше, чем это абсолютно необходимо.

2-й до последнегозначение, где точность каждого значения равна 20, результирующая точность равна 41, который нужно уменьшить только на 3, оставляя более легкое уменьшение в масштабной части.

(30,15) работает, потому чторезультирующая шкала равна 30, поэтому, когда она уменьшается, она все еще достаточно велика, чтобы содержать желаемое значение.

Урок: не делайте точность и масштабируйте больше, чем нужно, иначе вы получите странные результаты.

2 голосов
/ 17 ноября 2010

Ответ заключается в том, как компьютеры представляют числа внутри.В зависимости от используемой точности SQL Server выделит 5, 9, 13 или 17 байт для представления вашего числа (см. http://msdn.microsoft.com/en-us/library/ms187746(v=SQL.90).aspx) Так, например, когда вы перешли с точности 30 на точность 20, внутреннее представление переместилось из17 байт до 13 байт. Как установить масштаб для 17-байтового числа по сравнению с 13-байтовым числом, где большая часть числового представления предназначена для масштаба (15/30 = 0,5, 15/20 = 0,75, изменяет поведение округленияНе существует идеального ответа. Типы чисел, которые у нас есть, достаточно хороши для большинства приложений, но иногда вы получаете странные артефакты, которые вы видите, из-за того, как мы скомпрометировали представление чисел на компьютерах.

Кроме того, будьте очень, очень осторожны с типами с плавающей запятой. Они только приблизительно приближают числа и дают очень неправильные результаты при использовании в количестве. Они превосходны для большинства научных приложений, когда не более 20 чисел с плавающей запятой используются водин расчет. При использовании в количестве, скажем, adding 1 миллион чисел с плавающей запятой в сумме (column_name) вы получите мусор.Демонстрация ниже:

DECLARE @f FLOAT
DECLARE @n NUMERIC(20,10)
DECLARE @i INT

SET @f = 0
SET @n = 0
SET @i = 0

WHILE @i < 1000000
BEGIN
    SET @f = @f + 0.00000001
    SET @n = @n + 0.00000001
    SET @i = @i + 1
END

SELECT @n as [Numeric], @f as [Float]

Это дает мне следующий ответ на SQL Server 2008.

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