---
slug: /ru/sql-reference/data-types/decimal
sidebar_position: 42
sidebar_label: Decimal
---

# Decimal(P, S), Decimal32(S), Decimal64(S), Decimal128(S), Decimal256(S) {#decimalp-s-decimal32s-decimal64s-decimal128s}

Знаковые дробные числа с сохранением точности операций сложения, умножения и вычитания. Для деления осуществляется отбрасывание (не округление) знаков, не попадающих в младший десятичный разряд.

## Параметры {#parametry}

-   P - precision. Значение из диапазона \[ 1 : 76 \]. Определяет, сколько десятичных знаков (с учетом дробной части) может содержать число.
-   S - scale. Значение из диапазона \[ 0 : P \]. Определяет, сколько десятичных знаков содержится в дробной части числа.

В зависимости от параметра P Decimal(P, S) является синонимом:
- P из \[ 1 : 9 \] - для Decimal32(S)
- P из \[ 10 : 18 \] - для Decimal64(S)
- P из \[ 19 : 38 \] - для Decimal128(S)
- P из \[ 39 : 76 \] - для Decimal256(S)

## Диапазоны Decimal {#diapazony-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) )
-   Decimal256(S) - ( -1 \* 10^(76 - S), 1 \* 10^(76 - S) )

Например, Decimal32(4) содержит числа от -99999.9999 до 99999.9999 c шагом 0.0001.

## Внутреннее представление {#vnutrennee-predstavlenie}

Внутри данные представляются как знаковые целые числа, соответсвующей разрядности. Реальные диапазоны, хранящиеся в ячейках памяти несколько больше заявленных. Заявленные диапазоны Decimal проверяются только при вводе числа из строкового представления.
Поскольку современные CPU не поддерживают 128-битные и 256-битные числа, для операций над Decimal128 и Decimal256 эмулируются программно. Данные типы работают в разы медленнее, чем Decimal32/Decimal64.

## Операции и типы результата {#operatsii-i-tipy-rezultata}

Результат операции между двумя Decimal расширяется до большего типа (независимо от порядка аргументов).

-   `Decimal64(S1) <op> Decimal32(S2) -> Decimal64(S)`
-   `Decimal128(S1) <op> Decimal32(S2) -> Decimal128(S)`
-   `Decimal128(S1) <op> Decimal64(S2) -> Decimal128(S)`
-   `Decimal256(S1) <op> Decimal<32|64|128>(S2) -> Decimal256(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 может отличаться, несмотря на одинаковый тип результата.

## Проверка переполнений {#proverka-perepolnenii}

При выполнении операций над типом Decimal могут происходить целочисленные переполнения. Лишняя дробная часть отбрасывается (не округляется). Лишняя целочисленная часть приводит к исключению.

:::warning
Проверка переполнения не реализована для Decimal128 и Decimal256. В случае переполнения неверный результат будёт возвращён без выбрасывания исключения.
:::

``` 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.
```

**Смотрите также**
-   [isDecimalOverflow](../../sql-reference/functions/other-functions.md#is-decimal-overflow)
-   [countDigits](../../sql-reference/functions/other-functions.md#count-digits)
