Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 По какому правиму вычисляется scale выражения?  [new]
Округленный Decimal
Guest
declare
  @qty decimal(24,8),
  @percent decimal(24,8);
set @qty=0.00000160;
set @percent=100;
;with cte as (
  select @qty q1,
  @qty*@percent q2,
  @qty*@percent/100 q3
)
select q1,q2,q3 from cte

- выводит 0.00000160, 0.000160, и 0.000001 - т.е. произвошла потеря масштаба (scale). Пробуем проверить, что за типы вернул запрос:
declare
  @qty decimal(24,8),
  @percent decimal(24,8);
set @qty=0.00000160;
set @percent=100;
;with cte as (
  select @qty q1,
  @qty*@percent q2,
  @qty*@percent/100 q3
)
select
  sql_variant_property(q1, 'BaseType'),
  sql_variant_property(q1, 'Precision'),
  sql_variant_property(q1, 'Scale'),
  sql_variant_property(q2, 'BaseType'),
  sql_variant_property(q2, 'Precision'),
  sql_variant_property(q2, 'Scale'),
  sql_variant_property(q3, 'BaseType'),
  sql_variant_property(q3, 'Precision'),
  sql_variant_property(q3, 'Scale')
from cte

- для q1 нам выводится decimal 24 8, а для q2 и q3 - decimal 38 6. Согласно тому, что написано здесь: http://msdn.microsoft.com/en-us/library/ms190476.aspx - с precision результата всё вполне предсказуемо - для произведения (например) они просто складыаются, если результат больше 38 - оставляем 38. А вот про scale, вычисляемый по приведенным формулам, написано туманно:
When a result precision is greater than 38, the corresponding scale is reduced to prevent the integral part of a result from being truncated.

т.е. как именно он reduced - остается догадываться. Как именно в данном случае вычислялся scale?
P.S. Сервер:

Microsoft SQL Server 2012 - 11.0.5556.0 (X64)
Oct 31 2014 16:50:24
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)
30 дек 14, 09:09    [17070830]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Ruuu
Member

Откуда: Иркутск
Сообщений: 4272
Округленный Decimal
Согласно тому, что написано здесь: http://msdn.microsoft.com/en-us/library/ms190476.aspx - с precision результата всё вполне предсказуемо - для произведения (например) они просто складыаются, если результат больше 38 - оставляем 38. А вот про scale, вычисляемый по приведенным формулам, написано туманно:
When a result precision is greater than 38, the corresponding scale is reduced to prevent the integral part of a result from being truncated.

т.е. как именно он reduced - остается догадываться. Как именно в данном случае вычислялся scale?
P.S. Сервер:
Можно предположить, что scale не усекается меньше шести разрядов. Хотя подтверждения этого в документации найти не удалось.

А зачем вы для процента задали тип данных decimal(24,8)? У вас может быть триллиард процентов?
30 дек 14, 09:45    [17070992]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Округленный Decimal
Guest
Ruuu
А зачем вы для процента задали тип данных decimal(24,8)? У вас может быть триллиард процентов?

В процессе возни с некоей внешней (т.е. поставляемой) системой возникли проблемы с потерей масштаба вычислений, а я просто воспроизвел проблему "на пальцах", в самом простом виде. И да, там проценты хранятся в decimal(24,8), зачем - не знаю. Могу предположить, что просто из соображений единого подхода - система большая, и практически всё, что в ней есть с дробной частью, хранится в decimal(24,8). Собственно, проблему потери масштаба обошли кастованием одного из операндов к decimal(24,10), но хотелось бы разобраться в том, что происходит - как сервер определяет scale выражения. Чтобы потом не подбирать масштаб методом научного тыка, а заранее знать его.
30 дек 14, 10:04    [17071079]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
хмхмхм
Guest
Ruuu
Можно предположить, что scale не усекается меньше шести разрядов. Хотя подтверждения этого в документации найти не удалось.


Не совсем так, если s1+s2 >= 6, то да, похоже, что не усекается ниже.
Если же s1+s2 < 6, то усекается до (s1+s2).

Похоже, что в формуле 3 есть некая неточность и она упрощена, более правдоподобно участие магического число 6, как в формуле при делении.

Operation Result precision Result scale *
e1 + e2 max(s1;s2) + max(p1-s1;p2-s2) + 1 max(s1;s2)
e1 - e2 max(s1;s2) + max(p1-s1;p2-s2) + 1 max(s1;s2)
e1 * e2 p1 + p2 + 1 s1 + s2
e1 / e2 p1 - s1 + s2 + max(6;s1 + p2 + 1) max(6;s1 + p2 + 1)
e1 { UNION | EXCEPT | INTERSECT } e2 max(s1;s2) + max(p1-s1;p2-s2) max(s1;s2)
e1 % e2 min(p1-s1;p2 -s2) + max( s1;s2 ) max(s1;s2)
30 дек 14, 11:43    [17071706]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 6203
хмхмхм
более правдоподобно участие магического число 6, как в формуле при делении.

Так если оба операнда decimal(24,8), то max(6;s1 + p2 + 1)=33. А в случае топикстартера scale=6 (и, как я понял, 7 при decimal(24,10)). Всё равно не сходится.
30 дек 14, 11:50    [17071764]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
хмхмхм
Guest
Сон Веры Павловны,

вызывает интерес усечение scale при произведении.
вот например:

declare
  @qty decimal(28,13),
  @percent decimal(11,3);
set @qty=0.00000160;
set @percent=100;
;with cte as (
  select 
  @qty*@percent q2
)
select
  sql_variant_property(q2, 'BaseType'),
  sql_variant_property(q2, 'Precision'),
  sql_variant_property(q2, 'Scale')
from cte



Получаем Precision = 38 (т.к. 28+11+1 > 38).
Получаем сумму усечения 38-(28+11+1)= -2
Теперь по формуле из MSDN суммируем scale1 и scale2:
13+3=16

и затем усекаем его на -2, получаем 14.
Т.е. в этом примере все логично и decimal будет иметь Precision = 38, а Scale = 14.

А вот если теперь мы посмотрим другой пример, где сумма усечения = -14, то


declare
  @qty decimal(28,13),
  @percent decimal(23,3);
set @qty=0.00000160;
set @percent=100;
;with cte as (
  select 
  @qty*@percent q2
)
select
  sql_variant_property(q2, 'BaseType'),
  sql_variant_property(q2, 'Precision'),
  sql_variant_property(q2, 'Scale')
from cte


Увидим, что scale усекся до 6. Вот это и не очень понятно.
30 дек 14, 12:01    [17071841]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8834
Округленный Decimal,

это происходит из-за переполнения формата числа, ограниченного 38 цифрами.

выражение
e1 * e2

масштаб
p1 + p2 + 1

точность
s1 + s2

declare
  @qty decimal(11,8),
  @percent decimal(11,8);
set @qty=0.00000160;
set @percent=100.0;

;with cte as (
  select @qty q1,
  @qty*@percent q2,
  @qty*@percent/100.0 q3
)
select q1,q2,q3 from cte

Используйте явное преобразование в Вашем примере.
30 дек 14, 12:20    [17071993]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Glory
Member

Откуда:
Сообщений: 104751
хмхмхм
Увидим, что scale усекся до 6. Вот это и не очень понятно.

А что непонятного то ?
"scale is reduced to prevent the integral part of a result from being truncated"
Какой размер целой части результата при @percent decimal(23,3) и при @percent decimal(11,3); ??
30 дек 14, 12:44    [17072206]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Округленный Decimal
Guest
Владислав Колосов,

почему уменьшается scale, я прекрасно понимаю, как с этим справиться, тоже нашел. Интересуют именно правила уменьшения scale. Почему в случае с decimal(24,8) scale уменьшается до 6? А в случае с decimal(24,10) - до 7?
Поискл по интернетам - нашел, например, вот такое: Multiplication and Division with Numerics - SQL Programmability & API Development Team Blog - Site Home - MSDN Blogs
How much scale should be sacrificed? There is no right answer.
30 дек 14, 12:46    [17072227]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
msLex
Member

Откуда:
Сообщений: 9303
Glory
хмхмхм
Увидим, что scale усекся до 6. Вот это и не очень понятно.

А что непонятного то ?
"scale is reduced to prevent the integral part of a result from being truncated"
Какой размер целой части результата при @percent decimal(23,3) и при @percent decimal(11,3); ??

c 23,3 + 11,3 как раз все понятно, а вот в примере с
@qty decimal(28,13),
@percent decimal(23,3);

действительно происходит незадокументированная "магия" с итоговым scale = 6
30 дек 14, 12:49    [17072245]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Glory
Member

Откуда:
Сообщений: 104751
msLex
действительно происходит незадокументированная "магия" с итоговым scale = 6

Какая он недокументированная,если целые части операндов увеличиваются?
За счет чего увеличить целую часть результата при этом ?
30 дек 14, 12:52    [17072269]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
хмхмхм
Guest
Glory
хмхмхм
Увидим, что scale усекся до 6. Вот это и не очень понятно.

А что непонятного то ?
"scale is reduced to prevent the integral part of a result from being truncated"
Какой размер целой части результата при @percent decimal(23,3) и при @percent decimal(11,3); ??


Непонятно почему он в одних случаях усекается на разницу между 38 и p1+p2, а в других до 6.
30 дек 14, 12:52    [17072271]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Glory
Member

Откуда:
Сообщений: 104751
хмхмхм
Непонятно почему он в одних случаях усекается на разницу между 38 и p1+p2, а в других до 6.

А при @percent decimal(12,3); будет 38-13
при @percent decimal(13,3);будет 38-12
при @percent decimal(14,3);будет 38-11
Усекаешь ?
Целая часть результата растет и приходится "scale is reduced to prevent the integral part of a result from being truncated"
30 дек 14, 12:54    [17072295]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
msLex
Member

Откуда:
Сообщений: 9303
Glory
Какая он недокументированная,если целые части операндов увеличиваются?
За счет чего увеличить целую часть результата при этом ?

почему scale = 6?
30 дек 14, 12:55    [17072299]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Glory
Member

Откуда:
Сообщений: 104751
msLex
Glory
Какая он недокументированная,если целые части операндов увеличиваются?
За счет чего увеличить целую часть результата при этом ?

почему scale = 6?

А сколько должен быть то ?
30 дек 14, 12:56    [17072312]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
msLex
Member

Откуда:
Сообщений: 9303
Glory
msLex
пропущено...

почему scale = 6?

А сколько должен быть то ?

для
@qty decimal(28,13),
@percent decimal(23,3);
по формуле из хелпа

s1 + s2 - (38 - p1 + p2 + 1) = 13 + 3 - (38 - 28 + 23 + 1) = 2
30 дек 14, 13:00    [17072335]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Glory
Member

Откуда:
Сообщений: 104751
msLex
Glory
пропущено...

А сколько должен быть то ?

для
@qty decimal(28,13),
@percent decimal(23,3);
по формуле из хелпа

s1 + s2 - (38 - p1 + p2 + 1) = 13 + 3 - (38 - 28 + 23 + 1) = 2

Разве это не формула для деления ?
А здесь
;with cte as (
  select 
  @qty*@percent q2
)

умножение
30 дек 14, 13:03    [17072363]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
msLex
Member

Откуда:
Сообщений: 9303
Glory
msLex
пропущено...

для
@qty decimal(28,13),
@percent decimal(23,3);
по формуле из хелпа

s1 + s2 - (38 - p1 + p2 + 1) = 13 + 3 - (38 - 28 + 23 + 1) = 2

Разве это не формула для деления ?
А здесь
;with cte as (
  select 
  @qty*@percent q2
)


умножение

это формула для умножения
p = p1 + p2 + 1
s = s1 + s2 *
* The result precision and scale have an absolute maximum of 38. When a result precision is greater than 38, the corresponding scale is reduced to prevent the integral part of a result from being truncated.
т.е. в случае p > 38, s = s - (38- p)
30 дек 14, 13:09    [17072409]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 6203
Вроде как получается так: если s1+s2-(p1+p2+1-38)>6, то s=s1+s2-(p1+p2+1-38), иначе s=6 (это для случая, когда p1+p2+1<38). 6 - минимальный масштаб, до которого он может уменьшаться - вроде как исторически сложившаяся константа, выше по ссылке на блог МСДН это есть.
30 дек 14, 13:11    [17072415]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Glory
Member

Откуда:
Сообщений: 104751
msLex
т.е. в случае p > 38, s = s - (38- p)

Это вы так "scale is reduced" материализовали в формулу ?
А "prevent the integral part of a result from being truncated" тоже можете формулой выразить ?
30 дек 14, 13:14    [17072435]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 6203
Сон Веры Павловны
Вроде как получается так: если s1+s2-(p1+p2+1-38)>6, то s=s1+s2-(p1+p2+1-38), иначе s=6 (это для случая, когда p1+p2+1<38). 6 - минимальный масштаб, до которого он может уменьшаться - вроде как исторически сложившаяся константа, выше по ссылке на блог МСДН это есть.

Не, всё равно не укладывается:
declare
	@a decimal(38,22);
set @a=0.00000160;
;with cte(n) as (select @a*@a)
select
	sql_variant_property(n, 'Precision'),
	sql_variant_property(n, 'Scale')
from cte

38 6
declare
	@a decimal(38,23);
set @a=0.00000160;
;with cte(n) as (select @a*@a)
select
	sql_variant_property(n, 'Precision'),
	sql_variant_property(n, 'Scale')
from cte

38 7
30 дек 14, 13:20    [17072476]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
msLex
Member

Откуда:
Сообщений: 9303
Glory
msLex
т.е. в случае p > 38, s = s - (38- p)

Это вы так "scale is reduced" материализовали в формулу ?
А "prevent the integral part of a result from being truncated" тоже можете формулой выразить ?

Это я перевел всю фразу целиком,

в ней написано, что если p > 38, то будем уменьшать scale, для предотвращения потерь в целой части.
целая часть = P-S (это вроде очевидно). Если у нас P превысил максимум, то для сохранения целой части (P-S = const ) вам необходимо уменьшить S на столько же, на сколько превышен максимум P.
30 дек 14, 13:48    [17072661]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Glory
Member

Откуда:
Сообщений: 104751
msLex
Это я перевел всю фразу целиком,

в ней написано, что если p > 38, то будем уменьшать scale, для предотвращения потерь в целой части.
целая часть = P-S (это вроде очевидно). Если у нас P превысил максимум, то для сохранения целой части (P-S = const ) вам необходимо уменьшить S на столько же, на сколько превышен максимум P.

Целая часть десятичного числа - это знаки слева до запятой
Какая целая часть у 0.00000160 ? а у 100 ? А у результата их умножения ?
По формулам выходит
e1 * e2 - p1 + p2 + 1 - s1 + s2
38+23+1 - 13+3 -
62 и 16
Даже если 62 правращается в 38, то почему 16 должно превратиться в 2 то ?
Разве например 38,16 не хватает для хранения результата 0.00000160 * 100
30 дек 14, 13:58    [17072761]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
msLex
Member

Откуда:
Сообщений: 9303
Glory,

может тогда расскажите почему

declare
  @qty decimal(21,4) = 1e16
 , @percent decimal(21,4) = 1e16
select @qty*@percent


падает, а не приводит результат к decimal(38, 4), которого достаточно для хранения результата (и который вполне соответствует документации)?
30 дек 14, 14:55    [17073109]     Ответить | Цитировать Сообщить модератору
 Re: По какому правиму вычисляется scale выражения?  [new]
Glory
Member

Откуда:
Сообщений: 104751
msLex
падает, а не приводит результат к decimal(38, 4), которого достаточно для хранения результата (и который вполне соответствует документации)?

38,4 недостатчно для хранения целой части произведения 10000000000000000.0000 * 10000000000000000.0000
А вот произведения 1e-16 * 1e-16 или 1e16 * 1e-16
declare
  @qty decimal(21,4) = 1e-16
 , @percent decimal(21,4) = 1e-16

select @qty,@percent

целая часть произведения помещается в 38,4
Потому что дробную часть можно is reduced, а вот целую - нельзя
30 дек 14, 15:01    [17073142]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить