Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / scale у результата умножения decimal на int / 11 сообщений из 11, страница 1 из 1
21.02.2020, 13:13
    #39929437
Smile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
scale у результата умножения decimal на int
Друзья, не могу разобраться, почему масштаб результата вычислений (res_s) получается таким. Помогите, пожалуйста.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
SELECT @@VERSION

SELECT 
	'5592/24342' frac,
	CAST(5592 AS DECIMAL) nom,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL), 'BaseType') [nom_type],
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL), 'Precision') nom_p,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL), 'Scale') nom_s,

	CAST(24342 AS DECIMAL) denom,
	SQL_VARIANT_PROPERTY(CAST(24342 AS DECIMAL), 'BaseType') [denom_type],
	SQL_VARIANT_PROPERTY(CAST(24342 AS DECIMAL), 'Precision') denom_p,
	SQL_VARIANT_PROPERTY(CAST(24342 AS DECIMAL), 'Scale') denom_s,

	CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL) e1,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL), 'BaseType') [e1_type],
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL), 'Precision') p1,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL), 'Scale') s1,
	
	100 e2,
	SQL_VARIANT_PROPERTY(100, 'BaseType') [e2_type],
	SQL_VARIANT_PROPERTY(100, 'Precision') p2,
	SQL_VARIANT_PROPERTY(100, 'Scale') s2,
		
	CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL)*100 res,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL)*100, 'BaseType') res_type,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL)*100, 'Precision') res_p,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL)*100, 'Scale') res_s



----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Microsoft SQL Server 2012 (SP4) (KB4018073) - 11.0.7001.0 (X64)
Aug 15 2017 10:23:29
Copyright (c) Microsoft Corporation
Enterprise Edition: Core-based Licensing (64-bit) on Windows NT 6.3 <X64> (Build 9600: )

fracnomnom_typenom_pnom_sdenomdenom_typedenom_pdenom_se1e1_typep1s1e2e2_typep2s2resres_typeres_pres_s5592/243425592decimal18024342decimal1800.2297263988168597485decimal3719100int10022.9726398816859749decimal38 16

Читаю здесь

Код: plaintext
1.
2.
Операция	Точность результата	Масштаб результата *
...
e1 * e2	p1 + p2 + 1	s1 + s2


Операция e1 * e2
Точность p1 + p2 + 1 (37+10+1 = 48)
Масштаб s1 + s2 (19+0=19)

Итого 48.19

* Точность и масштаб результата имеют абсолютный максимум, равный 38. Если точность результата превышает 38, она уменьшается до 38 и уменьшается соответствующий масштаб, чтобы по возможности предотвратить усечение целой части результата. В некоторых случаях, например при умножении или делении, масштаб не уменьшается, чтобы сохранить десятичную точность, хотя при этом может возникнуть ошибка переполнения.
...
При выполнении операций умножения и деления требуется precision - scale разрядов для хранения целой части результата. Масштаб может уменьшаться согласно приведенным ниже правилам.
Итоговый масштаб уменьшается до min(scale, 38 - (precision-scale)), если целая часть короче 32 разрядов, так как он не может быть больше 38 - (precision-scale). В этом случае результат может округляться.
Масштаб не изменяется, если он меньше 6 и если целая часть длиннее 32 разрядов. В этом случае может возникнуть ошибка переполнения, если число не помещается в decimal(38, scale).
Масштаб будет задан равным 6, если он больше 6 и если целая часть длиннее 32 разрядов. В этом случае уменьшаются как целая часть, так и масштаб, и итоговым типом будет decimal(38,6). Результат может округляться до 6 десятичных знаков, либо может возникнуть ошибка переполнения, когда целая часть не помещается в 32 разряда.
...
Примеры
Следующее выражение возвращает результат 0.00000090000000000 без округления, так как он помещается в decimal(38,17):
SQL


select cast(0.0000009000 as decimal(30,20)) * cast(1.0000000000 as decimal(30,20)) [decimal 38,17]
В этом случае точность равна 61, а масштаб — 40. Целая часть (точность – масштаб = 21) короче 32 разрядов, поэтому это случай (1) в правилах умножения и масштаб вычисляется как min(scale, 38 - (precision-scale)) = min(40, 38 - (61-40)) = 17. Тип результата — decimal(38,17).




Целая часть 48-19 = 29 (короче 32 разрядов), значит "итоговый" масштаб min(scale, 38 - (precision-scale)) = min(19, 38 - (48-19))=9
Итого должно быть 38.9

Что я делаю не так?
...
Рейтинг: 0 / 0
21.02.2020, 13:28
    #39929445
msLex
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
scale у результата умножения decimal на int
По вашей же ссылке


* Точность и масштаб результата имеют абсолютный максимум, равный 38. Если точность результата превышает 38, она уменьшается до 38 и уменьшается соответствующий масштаб, чтобы по возможности предотвратить усечение целой части результата.
...
Рейтинг: 0 / 0
21.02.2020, 13:48
    #39929453
Smile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
scale у результата умножения decimal на int
msLex,

До уменьшения и получается 48.19. Вопрос не в том, почему они уменьшаются, вопрос, почему они уменьшаются сервером до 38.16, а по моим расчетам (согласно ссылке) должны до 38.9. Вероятно, я не правильно понимаю написанное по ссылке и мои расчеты не правильные. Но вроде нет же.
...
Рейтинг: 0 / 0
21.02.2020, 15:04
    #39929522
daw
daw
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
scale у результата умножения decimal на int
умножать decimal на int сервер не умеет - это разные типы. поэтому, перед умножением 100 приводится к decimal с минимально возможным precision. то есть p2 будет равно не 10, а 3.
...
Рейтинг: 0 / 0
21.02.2020, 15:42
    #39929546
Smile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
scale у результата умножения decimal на int
Ого. Если я туже сотню привожу явно к DECIMAL(10,0), то получается то, что я и ожидаю (по документации) - 38.9.
Т.е. с точностью/масштабом для INT, не смотря на то, что он мне их показывает как 10.0 (предыдущий запрос), он действительно что-то делает перед умножением на него DECIMAL. Только вот об этом ни слова по ссылке.

Наоборот

авторВ приведенной ниже таблице показано, как вычисляется точность и масштаб результата, если результат операции имеет тип decimal. Результат имеет тип decimal, если выполняется одно из следующих условий:
Оба выражения имеют тип decimal.
Одно выражение имеет тип decimal, а другое имеет тип данных со старшинством меньше, чем decimal.


А INT "старшинством меньше", чем DECIMAL. Т.е. ничего не должен как бы делать


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
SELECT 
	'5592/24342' frac,
	CAST(5592 AS DECIMAL) nom,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL), 'BaseType') [nom_type],
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL), 'Precision') nom_p,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL), 'Scale') nom_s,

	CAST(24342 AS DECIMAL) denom,
	SQL_VARIANT_PROPERTY(CAST(24342 AS DECIMAL), 'BaseType') [denom_type],
	SQL_VARIANT_PROPERTY(CAST(24342 AS DECIMAL), 'Precision') denom_p,
	SQL_VARIANT_PROPERTY(CAST(24342 AS DECIMAL), 'Scale') denom_s,

	CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL) e1,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL), 'BaseType') [e1_type],
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL), 'Precision') p1,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL), 'Scale') s1,
	
	CAST(100 AS DECIMAL(10,0)) e2,
	SQL_VARIANT_PROPERTY(CAST(100 AS DECIMAL(10,0)), 'BaseType') [e2_type],
	SQL_VARIANT_PROPERTY(CAST(100 AS DECIMAL(10,0)), 'Precision') p2,
	SQL_VARIANT_PROPERTY(CAST(100 AS DECIMAL(10,0)), 'Scale') s2,
		
	CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL)*CAST(100 AS DECIMAL(10,0)) res,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL)*CAST(100 AS DECIMAL(10,0)), 'BaseType') res_type,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL)*CAST(100 AS DECIMAL(10,0)), 'Precision') res_p,
	SQL_VARIANT_PROPERTY(CAST(5592 AS DECIMAL) / CAST(24342 AS DECIMAL)*CAST(100 AS DECIMAL(10,0)), 'Scale') res_s



fracnomnom_typenom_pnom_sdenomdenom_typedenom_pdenom_se1e1_typep1s1e2e2_typep2s2resres_typeres_pres_s5592/243425592decimal18024342decimal1800.2297263988168597485decimal3719100decimal10022.972639882decimal38 9
...
Рейтинг: 0 / 0
21.02.2020, 15:46
    #39929550
Smile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
scale у результата умножения decimal на int
daw
умножать decimal на int сервер не умеет - это разные типы. поэтому, перед умножением 100 приводится к decimal с минимально возможным precision. то есть p2 будет равно не 10, а 3.


допер, спасибо! Он мне показывает в результатах запроса precision INT до умножения. А то, что он его еще уменьшает на сколько можно (видимо, что бы повысить точность вычислений) перед (ну или там во время) самими умножением, я, разумеется, не вижу.
Где бы еще почитать про такое его поведение...
...
Рейтинг: 0 / 0
02.03.2020, 16:50
    #39933114
Smile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
scale у результата умножения decimal на int
Дабы не плодить темы...

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT 
	0.25 v1, 
	SQL_VARIANT_PROPERTY(0.25, 'BaseType') t1,
	SQL_VARIANT_PROPERTY(0.25, 'Precision') p1,
	SQL_VARIANT_PROPERTY(0.25, 'Scale') s1,

	CAST(0.25 AS DECIMAL) v2,
	SQL_VARIANT_PROPERTY(CAST(0.25 AS DECIMAL), 'BaseType') t2,
	SQL_VARIANT_PROPERTY(CAST(0.25 AS DECIMAL), 'Precision') p2,
	SQL_VARIANT_PROPERTY(CAST(0.25 AS DECIMAL), 'Scale') s2
	



v1t1p1s1v2t2p2s20.25numeric220decimal180

Почему такие p2, s2 и, следовательно, v2 — понятно (18.0 по умолчанию, я сам указал DECIMAL).
Но почему такие p1 и s1? Почему для 0.25 сервер выбирает точность 2.2, т.е. без десятичных знаков?
...
Рейтинг: 0 / 0
02.03.2020, 16:52
    #39933117
msLex
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
scale у результата умножения decimal на int
Smile
Почему для 0.25 сервер выбирает точность 2.2, т.е. без десятичных знаков?

Минимально необходимый.
Хотите задать сами - используйте cast или предварительно объявленную переменную нужного вам типа.
...
Рейтинг: 0 / 0
02.03.2020, 17:13
    #39933131
Smile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
scale у результата умножения decimal на int
msLex,

ну так вопрос в том и есть, чем в данном случае определилась минимальная необходимость? 0.25 нулем же становится на "пустом" месте. Во втором случае я из 0.25 сам явно сделал ноль
...
Рейтинг: 0 / 0
02.03.2020, 17:20
    #39933134
msLex
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
scale у результата умножения decimal на int
Smile
msLex,

ну так вопрос в том и есть, чем в данном случае определилась минимальная необходимость? 0.25 нулем же становится на "пустом" месте. Во втором случае я из 0.25 сам явно сделал ноль



Вы про cast(0.25 as decimal)?

decimal без "()" = decimal(18, 0)


https://docs.microsoft.com/ru-ru/sql/t-sql/data-types/decimal-and-numeric-transact-sql?view=sql-server-ver15
...
Рейтинг: 0 / 0
02.03.2020, 17:22
    #39933135
Smile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
scale у результата умножения decimal на int
msLex, ну нет же.
Про
авторdecimal без "()" = decimal(18, 0)
нет и не было вопросов.

Вопрос в том, почему под 0.25 (без кастования) он выделяет 2.2









Все, я извиняюсь. Дико туплю...
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / scale у результата умножения decimal на int / 11 сообщений из 11, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]