Арифметические функции
Арифметические функции работают с любыми двумя операндами типов UInt8
, UInt16
, UInt32
, UInt64
, Int8
, Int16
, Int32
, Int64
, Float32
или Float64
.
Перед выполнением операции оба операнда приводятся к типу результата. Тип результата определяется следующим образом (если не указано иное в документации функций ниже):
- Если оба операнда имеют ширину до 32 бит, размер типа результата будет равен размеру следующего большего типа, следующего за большим из двух операндов (повышение размера целого числа). Например,
UInt8 + UInt16 = UInt32
илиFloat32 * Float32 = Float64
. - Если один из операндов имеет 64 бита или более, размер типа результата будет равен размеру большего из двух операндов. Например,
UInt32 + UInt128 = UInt128
илиFloat32 * Float64 = Float64
. - Если один из операндов со знаком, тип результата также будет со знаком, в противном случае он будет без знака. Например,
UInt32 * Int32 = Int64
.
Эти правила гарантируют, что тип результата будет самым маленьким типом, который может представлять все возможные результаты. Хотя это вводит риск переполнений в пределах диапазона значений, это гарантирует, что вычисления выполняются быстро, используя максимальную нативную ширину целых чисел в 64 бита. Это поведение также гарантирует совместимость со многими другими базами данных, которые предоставляют целые числа на 64 бита (BIGINT) как самый большой тип целого числа.
Пример:
Переполнения происходят так же, как в C++.
plus
Вычисляет сумму двух значений a
и b
.
Синтаксис
Можно сложить целое число и дату или дату с временем. Первая операция увеличивает количество дней в дате, вторая операция увеличивает количество секунд в дате с временем.
Псевдоним: a + b
(оператор)
minus
Вычисляет разность двух значений a
и b
. Результат всегда со знаком.
Подобно plus
, можно вычесть целое число из даты или даты с временем.
Кроме того, поддерживается вычитание между датами с временем, что дает разницу во времени между ними.
Синтаксис
Псевдоним: a - b
(оператор)
multiply
Вычисляет произведение двух значений a
и b
.
Синтаксис
Псевдоним: a * b
(оператор)
divide
Вычисляет частное двух значений a
и b
. Тип результата всегда Float64. Целочисленное деление осуществляется с помощью функции intDiv
.
Деление на 0 возвращает inf
, -inf
или nan
.
Синтаксис
Псевдоним: a / b
(оператор)
intDiv
Выполняет целочисленное деление двух значений a
на b
, т.е. вычисляет частное, округленное вниз до ближайшего меньшего целого.
Результат имеет такую же ширину, как делимое (первый параметр).
Исключение выбрасывается при делении на ноль, когда частное не помещается в диапазон делимого или при делении минимально отрицательного числа на минус один.
Синтаксис
Пример
Запрос:
intDivOrZero
То же, что и intDiv
, но возвращает ноль при делении на ноль или при делении минимально отрицательного числа на минус один.
Синтаксис
isFinite
Возвращает 1, если аргумент Float32 или Float64 не бесконечен и не является NaN, иначе эта функция возвращает 0.
Синтаксис
isInfinite
Возвращает 1, если аргумент Float32 или Float64 бесконечен, иначе эта функция возвращает 0. Обратите внимание, что 0 возвращается для NaN.
Синтаксис
ifNotFinite
Проверяет, является ли значение с плавающей точкой конечным.
Синтаксис
Аргументы
Возвращаемое значение
x
, еслиx
конечен.y
, еслиx
не конечен.
Пример
Запрос:
SELECT 1/0 as infimum, ifNotFinite(infimum,42)
Результат:
┌─infimum─┬─ifNotFinite(divide(1, 0), 42)─┐ │ inf │ 42 │ └─────────┴───────────────────────────────┘
Вы можете получить аналогичный результат, используя тернарный оператор: isFinite(x) ? x : y
.
isNaN
Возвращает 1, если аргумент Float32 и Float64 является NaN, иначе эта функция возвращает 0.
Синтаксис
modulo
Вычисляет остаток от деления двух значений a
на b
.
Тип результата является целым, если оба входа целые. Если один из входов является числом с плавающей запятой, тип результата будет Float64.
Остаток вычисляется так же, как в C++. Используется усеченное деление для отрицательных чисел.
Исключение выбрасывается при делении на ноль или при делении минимально отрицательного числа на минус один.
Синтаксис
Псевдоним: a % b
(оператор)
moduloOrZero
Как modulo, но возвращает ноль, когда делитель равен нулю.
Синтаксис
positiveModulo(a, b)
Как modulo, но всегда возвращает неотрицательное число.
Эта функция работает в 4-5 раз медленнее, чем modulo
.
Синтаксис
Псевдонимы:
positive_modulo(a, b)
pmod(a, b)
Пример
Запрос:
Результат:
negate
Отрицает значение a
. Результат всегда со знаком.
Синтаксис
Псевдоним: -a
abs
Вычисляет абсолютное значение a
. Не оказывает влияния, если a
является беззнаковым типом. Если a
является знаковым типом, возвращает беззнаковое число.
Синтаксис
gcd
Возвращает наибольший общий делитель двух значений a
и b
.
Исключение выбрасывается при делении на ноль или при делении минимально отрицательного числа на минус один.
Синтаксис
lcm(a, b)
Возвращает наименьшее общее кратное двух значений a
и b
.
Исключение выбрасывается при делении на ноль или при делении минимально отрицательного числа на минус один.
Синтаксис
max2
Возвращает большее из двух значений a
и b
. Возвращаемое значение имеет тип Float64.
Синтаксис
Пример
Запрос:
Результат:
min2
Возвращает меньшее из двух значений a
и b
. Возвращаемое значение имеет тип Float64.
Синтаксис
Пример
Запрос:
Результат:
multiplyDecimal
Умножает два десятичных числа a
и b
. Результат будет иметь тип Decimal256.
Масштаб результата может быть явно указан с помощью result_scale
. Если result_scale
не указан, предполагается, что он равен максимальному масштабу входных значений.
Эта функция работает значительно медленнее, чем обычное multiply
. В случае, если контроль над точностью результата не требуется и/или требуется быстрое вычисление, рекомендуется использовать multiply
.
Синтаксис
Аргументы
a
— Первое значение. Decimal.b
— Второе значение. Decimal.result_scale
— Масштаб результата. Int/UInt.
Возвращаемое значение
- Результат умножения с заданным масштабом. Decimal256.
Пример
Различия по сравнению с обычным умножением:
Результат:
Результат:
divideDecimal
Делит два десятичных числа a
и b
. Результат будет иметь тип Decimal256.
Масштаб результата может быть явно указан с помощью result_scale
. Если result_scale
не указан, предполагается, что он равен максимальному масштабу входных значений.
Эта функция работает значительно медленнее, чем обычное divide
. В случае, если контроль над точностью результата не требуется и/или требуется быстрое вычисление, рекомендуется использовать divide
.
Синтаксис
Аргументы
a
— Первое значение: Decimal.b
— Второе значение: Decimal.result_scale
— Масштаб результата: Int/UInt.
Возвращаемое значение
- Результат деления с заданным масштабом. Decimal256.
Пример
Различия по сравнению с обычным делением:
Результат:
Результат:
byteSwap
Обращает байты целого числа, т.е. изменяет его конец.
Синтаксис
Пример
Результат:
В приведенном выше примере можно работать следующим образом:
- Преобразовать десятичное целое число в эквивалентный шестнадцатеричный формат в формате big-endian, т.е. 3351772109 -> C7 C7 FB CD (4 байта)
- Обратить байты, т.е. C7 C7 FB CD -> CD FB C7 C7
- Преобразовать результат обратно в целое число, предполагая big-endian, т.е. CD FB C7 C7 -> 3455829959
Одним из случаев использования этой функции является изменение порядка байтов для IPv4: