Перейти к основному содержимому
Перейти к основному содержимому

Decimal, Decimal(P), Decimal(P, S), Decimal32(S), Decimal64(S), Decimal128(S), Decimal256(S)

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

Параметры

  • P - точность. Допустимый диапазон: [ 1 : 76 ]. Определяет, сколько десятичных цифр число может содержать (включая дробную часть). По умолчанию точность равна 10.
  • S - масштаб. Допустимый диапазон: [ 0 : P ]. Определяет, сколько десятичных цифр может содержать дробная часть.

Decimal(P) эквивалентен Decimal(P, 0). Аналогично, синтаксис Decimal эквивалентен Decimal(10, 0).

В зависимости от значения параметра 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

  • Decimal(P, S) - ( -1 * 10^(P - S), 1 * 10^(P - S) )
  • 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 с шагом 0.0001.

Внутреннее представление

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

Поскольку современные ЦП не поддерживают 128-битные и 256-битные целые числа на уровне аппаратуры, операции над Decimal128 и Decimal256 эмулируются. Таким образом, Decimal128 и Decimal256 работают значительно медленнее, чем Decimal32/Decimal64.

Операции и тип результата

Бинарные операции над 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)

Правила для масштаба:

  • сложение, вычитание: S = max(S1, S2).
  • умножение: S = S1 + S2.
  • деление: S = S1.

Для аналогичных операций между Decimal и целыми числами результат - Decimal того же размера, что и аргумент.

Операции между Decimal и Float32/Float64 не определены. Если вам нужно их использовать, вы можете явно привести один из аргументов, используя функции toDecimal32, toDecimal64, toDecimal128 или toFloat32, toFloat64. Имейте в виду, что результат потеряет точность, а преобразование типов является вычислительно затратной операцией.

Некоторые функции над Decimal возвращают результат в виде Float64 (например, var или stddev). Промежуточные вычисления могут по-прежнему выполняться в Decimal, что может привести к различным результатам между Float64 и Decimal с одинаковыми значениями.

Проверки переполнения

Во время вычислений с Decimal могут произойти переполнения целых чисел. Чрезмерные цифры в дробной части отбрасываются (не округляются). Чрезмерные цифры в целой части приведут к исключению.

осторожно

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

Проверки переполнения приводят к замедлению операций. Если известно, что переполнения невозможны, имеет смысл отключить проверки, используя настройку decimal_check_overflow. Когда проверки отключены и происходит переполнение, результат будет некорректным:

Проверки переполнения происходят не только при арифметических операциях, но и при сравнении значений:

Смотрите также