2013-04-08 5 views
5

У меня есть следующий набор вычислений в excel, который я хочу использовать в хранимой процедуре.Точность с плавающей запятой SQL, ограниченная 6 цифрами

Excel

CellA: 45/448.2 = 0.100401606425703 
CellB: 1-CellA = 0.899598393574297 
CellC: 1-CellB = 0.100401606425703 
CellD: CellC * 448.2 = 45.000000000000000 

В SQL я делаю следующее:

declare @a decimal(18,15) = 45/448.2 
declare @b decimal(18,15) = [email protected] 
declare @c decimal(18,15) = [email protected] 
declare @d decimal(18,15) = @c * 448.2 

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

declare @e decimal(18,15) = (1-(1-(45/448.2)))*448.2 

когда я возвращаю значения SQL дает мне следующее:

@a: 0.100401000000000 
@b: 0.899599000000000 
@c: 0.100401000000000 
@d: 44.999728200000000 

@e: 44.999728200000000 

Я попытался настроить точность десятичных знаков в SQL, но я ничего не меняю, он возвращает только первые 6 цифр десятичной дроби.

Обеспечивает ли Excel какую-либо оптимизацию при запуске формулы?

Любые идеи?

+0

Try, скажем, 'Выбор 45/CAST (448.2 AS DECIMAL (18,1)) '. [Ссылки здесь] (http://stackoverflow.com/a/5385417/73226) сообщают вам правила для результирующего типа данных деления. –

+0

@MartinSmith, который дает мне более полное десятичное значение для @a, хотя мой ответ 45.000000000000085 вы можете объяснить, почему? – ScampDoodle

+0

Это объясняется в двух ссылках предыдущего ответа, которые я слишком ленился, чтобы воспроизвести выше. 'e1/e2 дает p = p1 - s1 + s2 + max (6, s1 + p2 + 1), s = max (6, s1 + p2 + 1)'. Если 'p' будет'> 38', '' '' усекается на '6' –

ответ

7

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

declare @a decimal(18,15) = 45/448.2 
print @a 

дает

--------------------------------------- 
0.100401000000000 

Это из типов данных. Когда вы говорите

448.2 

это (за the documentation) интерпретируется как константа типа decimal и also per the documentation,

В Transact-SQL заявления, константа с десятичной точкой автоматически преобразуется в числовое значение данных, используя минимальную точность и масштабирование . Например, константа 12,345 является преобразуется в числовое значение с точностью 5 и масштабом 3.

Так 448.2 является decimal(4,3). 45 является integer, который в сочетании с decimalis treated as having precision of 10 and scale 0. Когда мы разделим, the rules сказать

Operation  Result precision      Result scale 
e1/e2  p1 - s1 + s2 + max(6, s1 + p2 + 1)  max(6, s1 + p2 + 1) 

, который в этом случае дает результат точность 10 - 3 + 0 + max(6, 0 + 3 + 1) и масштаб max(6, 0 + 3 + 1), который выходит на 13 и 6.

Эта шкала результатов 6, поэтому результат состоит только из шести знаков после запятой.

Способ исправления заключается в том, чтобы доставить ваши операнды в соответствующий тип, прежде чем действовать на них; например, вот два пути:

Принудительно число, которое следует рассматривать как с плавающей точкой:

declare @a decimal(18,15) = 45/448.2e0 
select @a 

--------------------------------------- 
0.100401606425703 

Явное поставить десятичную шкалу:

declare @a decimal(18,15) = 45/cast(448.2 as decimal(18,10)) 
select @a 

--------------------------------------- 
0.100401606425703 
+0

Это установило меня по правильному пути, мне пришлось настроить количество знаков после запятой, но в конечном итоге это был правильный ответ – ScampDoodle

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