powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / scale у результата умножения decimal на int
11 сообщений из 11, страница 1 из 1
scale у результата умножения decimal на int
    #39929437
Smile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Друзья, не могу разобраться, почему масштаб результата вычислений (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
scale у результата умножения decimal на int
    #39929445
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По вашей же ссылке


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

До уменьшения и получается 48.19. Вопрос не в том, почему они уменьшаются, вопрос, почему они уменьшаются сервером до 38.16, а по моим расчетам (согласно ссылке) должны до 38.9. Вероятно, я не правильно понимаю написанное по ссылке и мои расчеты не правильные. Но вроде нет же.
...
Рейтинг: 0 / 0
scale у результата умножения decimal на int
    #39929522
Фотография daw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
умножать decimal на int сервер не умеет - это разные типы. поэтому, перед умножением 100 приводится к decimal с минимально возможным precision. то есть p2 будет равно не 10, а 3.
...
Рейтинг: 0 / 0
scale у результата умножения decimal на int
    #39929546
Smile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ого. Если я туже сотню привожу явно к 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
scale у результата умножения decimal на int
    #39929550
Smile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
daw
умножать decimal на int сервер не умеет - это разные типы. поэтому, перед умножением 100 приводится к decimal с минимально возможным precision. то есть p2 будет равно не 10, а 3.


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

Код: 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
scale у результата умножения decimal на int
    #39933117
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Smile
Почему для 0.25 сервер выбирает точность 2.2, т.е. без десятичных знаков?

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

ну так вопрос в том и есть, чем в данном случае определилась минимальная необходимость? 0.25 нулем же становится на "пустом" месте. Во втором случае я из 0.25 сам явно сделал ноль
...
Рейтинг: 0 / 0
scale у результата умножения decimal на int
    #39933134
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
scale у результата умножения decimal на int
    #39933135
Smile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
msLex, ну нет же.
Про
авторdecimal без "()" = decimal(18, 0)
нет и не было вопросов.

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









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


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