|
scale у результата умножения decimal на int
|
|||
---|---|---|---|
#18+
Друзья, не могу разобраться, почему масштаб результата вычислений (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.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 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 (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 Что я делаю не так? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.02.2020, 13:13 |
|
scale у результата умножения decimal на int
|
|||
---|---|---|---|
#18+
По вашей же ссылке * Точность и масштаб результата имеют абсолютный максимум, равный 38. Если точность результата превышает 38, она уменьшается до 38 и уменьшается соответствующий масштаб, чтобы по возможности предотвратить усечение целой части результата. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.02.2020, 13:28 |
|
scale у результата умножения decimal на int
|
|||
---|---|---|---|
#18+
msLex, До уменьшения и получается 48.19. Вопрос не в том, почему они уменьшаются, вопрос, почему они уменьшаются сервером до 38.16, а по моим расчетам (согласно ссылке) должны до 38.9. Вероятно, я не правильно понимаю написанное по ссылке и мои расчеты не правильные. Но вроде нет же. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.02.2020, 13:48 |
|
scale у результата умножения decimal на int
|
|||
---|---|---|---|
#18+
умножать decimal на int сервер не умеет - это разные типы. поэтому, перед умножением 100 приводится к decimal с минимально возможным precision. то есть p2 будет равно не 10, а 3. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.02.2020, 15:04 |
|
scale у результата умножения decimal на int
|
|||
---|---|---|---|
#18+
Ого. Если я туже сотню привожу явно к 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.
fracnomnom_typenom_pnom_sdenomdenom_typedenom_pdenom_se1e1_typep1s1e2e2_typep2s2resres_typeres_pres_s5592/243425592decimal18024342decimal1800.2297263988168597485decimal3719100decimal10022.972639882decimal38 9 ... |
|||
:
Нравится:
Не нравится:
|
|||
21.02.2020, 15:42 |
|
scale у результата умножения decimal на int
|
|||
---|---|---|---|
#18+
daw умножать decimal на int сервер не умеет - это разные типы. поэтому, перед умножением 100 приводится к decimal с минимально возможным precision. то есть p2 будет равно не 10, а 3. допер, спасибо! Он мне показывает в результатах запроса precision INT до умножения. А то, что он его еще уменьшает на сколько можно (видимо, что бы повысить точность вычислений) перед (ну или там во время) самими умножением, я, разумеется, не вижу. Где бы еще почитать про такое его поведение... ... |
|||
:
Нравится:
Не нравится:
|
|||
21.02.2020, 15:46 |
|
scale у результата умножения decimal на int
|
|||
---|---|---|---|
#18+
Дабы не плодить темы... Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
v1t1p1s1v2t2p2s20.25numeric220decimal180 Почему такие p2, s2 и, следовательно, v2 — понятно (18.0 по умолчанию, я сам указал DECIMAL). Но почему такие p1 и s1? Почему для 0.25 сервер выбирает точность 2.2, т.е. без десятичных знаков? ... |
|||
:
Нравится:
Не нравится:
|
|||
02.03.2020, 16:50 |
|
scale у результата умножения decimal на int
|
|||
---|---|---|---|
#18+
Smile Почему для 0.25 сервер выбирает точность 2.2, т.е. без десятичных знаков? Минимально необходимый. Хотите задать сами - используйте cast или предварительно объявленную переменную нужного вам типа. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.03.2020, 16:52 |
|
scale у результата умножения decimal на int
|
|||
---|---|---|---|
#18+
msLex, ну так вопрос в том и есть, чем в данном случае определилась минимальная необходимость? 0.25 нулем же становится на "пустом" месте. Во втором случае я из 0.25 сам явно сделал ноль ... |
|||
:
Нравится:
Не нравится:
|
|||
02.03.2020, 17:13 |
|
scale у результата умножения decimal на int
|
|||
---|---|---|---|
#18+
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 ... |
|||
:
Нравится:
Не нравится:
|
|||
02.03.2020, 17:20 |
|
|
start [/forum/topic.php?fid=46&msg=39929550&tid=1686401]: |
0ms |
get settings: |
11ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
30ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
44ms |
get tp. blocked users: |
1ms |
others: | 334ms |
total: | 448ms |
0 / 0 |