ClickHouse/docs/ru/data_types/decimal.md
Sergei Bocharov 1f394202e6 Fix typos
2019-10-14 13:34:27 +03:00

97 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Decimal(P, S), Decimal32(S), Decimal64(S), Decimal128(S)
Знаковые дробные числа с сохранением точности операций сложения, умножения и вычитания. Для деления осуществляется отбрасывание (не округление) знаков, не попадающих в младший десятичный разряд.
## Параметры
- P - precision. Значение из диапазона [ 1 : 38 ]. Определяет, сколько десятичных знаков (с учетом дробной части) может содержать число.
- S - scale. Значение из диапазона [ 0 : P ]. Определяет, сколько десятичных знаков содержится в дробной части числа.
В зависимости от параметра P Decimal(P, S) является синонимом:
- P из [ 1 : 9 ] - для Decimal32(S)
- P из [ 10 : 18 ] - для Decimal64(S)
- P из [ 19 : 38 ] - для Decimal128(S)
## Диапазоны Decimal
- Decimal32(S) - ( -1 * 10^(9 - S), 1 * 10^(9 - S) )
- Decimal64(S) - ( -1 * 10^(18 - S), 1 * 10^(18 - S) )
- Decimal128(S) - ( -1 * 10^(38 - S), 1 * 10^(38 - S) )
Например, Decimal32(4) содержит числа от -99999.9999 до 99999.9999 c шагом 0.0001.
## Внутреннее представление
Внутри данные представляются как знаковые целые числа, соответсвующей разрядности. Реальные диапазоны, хранящиеся в ячейках памяти несколько больше заявленных. Заявленные диапазоны Decimal проверяются только при вводе числа из строкового представления.
Поскольку современные CPU не поддерживают 128-битные числа, операции над Decimal128 эмулируются программно. Decimal128 работает в разы медленней чем Decimal32/Decimal64.
## Операции и типы результата
Результат операции между двумя Decimal расширяется до большего типа (независимо от порядка аргументов).
- Decimal64(S1) <op> Decimal32(S2) -> Decimal64(S)
- Decimal128(S1) <op> Decimal32(S2) -> Decimal128(S)
- Decimal128(S1) <op> Decimal64(S2) -> Decimal128(S)
Для размера дробной части (scale) результата действуют следующие правила:
- сложение, вычитание: S = max(S1, S2).
- умножение: S = S1 + S2.
- деление: S = S1.
При операциях между Decimal и целыми числами результатом является Decimal, аналогичный аргументу.
Операции между Decimal и Float32/64 не определены. Для осуществления таких операций нужно явно привести один из аргументов функциями: toDecimal32, toDecimal64, toDecimal128, или toFloat32, toFloat64. Это сделано из двух соображений. Во-первых, результат операции будет с потерей точности. Во-вторых, преобразование типа - дорогая операция, из-за ее наличия пользовательский запрос может работать в несколько раз дольше.
Часть функций над Decimal возвращают Float64 (например, var, stddev). Для некоторых из них промежуточные операции проходят в Decimal.
Для таких функций результат над одинаковыми данными во Float64 и Decimal может отличаться, несмотря на одинаковый тип результата.
## Проверка переполнений
При выполнении операций над типом Decimal могут происходить целочисленные переполнения. Лишняя дробная часть отбрасывается (не округляется). Лишняя целочисленная часть приводит к исключению.
```sql
SELECT toDecimal32(2, 4) AS x, x / 3
```
```text
┌──────x─┬─divide(toDecimal32(2, 4), 3)─┐
│ 2.0000 │ 0.6666 │
└────────┴──────────────────────────────┘
```
```sql
SELECT toDecimal32(4.2, 8) AS x, x * x
```
```text
DB::Exception: Scale is out of bounds.
```
```sql
SELECT toDecimal32(4.2, 8) AS x, 6 * x
```
```text
DB::Exception: Decimal math overflow.
```
Проверка переполнения приводит к замедлению операций. При уверенности, что типа результата хватит для его записи проверку переполнения можно отключить настройкой decimal_check_overflow. В этом случае при переполнении вернется неверное значение:
```sql
SET decimal_check_overflow = 0;
SELECT toDecimal32(4.2, 8) AS x, 6 * x
```
```text
┌──────────x─┬─multiply(6, toDecimal32(4.2, 8))─┐
│ 4.20000000 │ -17.74967296 │
└────────────┴──────────────────────────────────┘
```
Переполнения происходят не только на арифметических операциях, но и на операциях сравнения. Отключать проверку стоит только при полной уверенности в корректности результата:
```sql
SELECT toDecimal32(1, 8) < 100
```
```text
DB::Exception: Can't compare.
```
[Оригинальная статья](https://clickhouse.yandex/docs/ru/data_types/decimal/) <!--hide-->