Документация Engee

Математические операции и элементарные функции

В Julia доступен полный набор основных арифметических и битовых операторов для всех числовых примитивных типов языка, а также эффективная и портируемая реализация комплексного набора стандартных математических функций.

Арифметические операторы

Для всех примитивных числовых типов поддерживаются следующие арифметические операторы.

Выражение Название Описание

+x

Унарный плюс

Операция тождественности

-x

Унарный минус

Отображает значения в их аддитивные инверсии.

x + y

Двоичный плюс

Выполняет сложение.

x - y

Двоичный минус

Выполняет вычитание.

x * y

Умножение

Выполняет умножение.

x / y

Деление

Выполняет деление.

x ÷ y

Целочисленное деление

x / y с округлением до целого числа.

x \ y

Деление с инверсией

Эквивалентно y / x.

x ^ y

Возведение в степень

Возводит x в степень y.

x % y

Остаток

Эквивалентно rem(x,y).

Помещение числового литерала непосредственно перед идентификатором или скобками, например 2x или 2(x+y), рассматривается как умножение, причем с большим приоритетом, чем у других двоичных операций. Подробнее: см. Числовые литеральные коэффициенты.

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

Для удобного ввода знака ÷ можно использовать \div<tab> в REPL или IDE Julia. Подробнее: см. раздел руководства о вводе символов Юникода.

Вот некоторые простые примеры использования арифметических операторов.

julia> 1 + 2 + 3
6

julia> 1 - 2
-1

julia> 3*2/12
0.5

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

При использовании в умножении значение false действует как сильный нуль.

julia> NaN * false
0.0

julia> false * Inf
0.0

Это позволяет предотвратить подстановку значений NaN в заведомо нулевых количествах. Обоснование: Кнут (1992).

Логические операторы

Для типов Bool поддерживаются следующие логические операторы.

Выражение Название

!x

Отрицание

x && y

Вычисляемое по сокращенной схеме «и»

x || y

Вычисляемое по сокращенной схеме «или»

Отрицание изменяет true на false и наоборот. Пояснения для операций вычисления по сокращенной схеме доступны по приведенным ссылкам.

Обратите внимание, что Bool представляет собой целочисленный тип и для него также определяются все стандартные правила продвижения и числовые операторы.

Битовые операторы

Для всех примитивных целочисленных типов поддерживаются следующие битовые операторы.

Выражение Название

~x

Битовое «не»

x & y

Битовое «и»

x | y

Битовое «или»

x ⊻ y

Битовое исключающее «или»

x ⊼ y

Битовое «и не»

x ⊽ y

Битовое «или не»

x >>> y

Логический сдвиг вправо

x >> y

Арифметический сдвиг вправо

x << y

Логический/арифметический сдвиг влево

Вот ряд примеров использования битовых операторов.

julia> ~123
-124

julia> 123 & 234
106

julia> 123 | 234
251

julia> 123 ⊻ 234
145

julia> xor(123, 234)
145

julia> nand(123, 123)
-124

julia> 123 ⊼ 123
-124

julia> nor(123, 124)
-128

julia> 123 ⊽ 124
-128

julia> ~UInt32(123)
0xffffff84

julia> ~UInt8(123)
0x84

Операторы с присваиванием

Все двоичные арифметические и битовые операторы также имеют версию с присваиванием, которая передает результат операнду, стоящему слева. Для использования версии двоичного оператора с присваиванием необходимо сразу после оператора указать знак =. Например, запись x += 3 эквивалентна x = x + 3.

julia> x = 1
1

julia> x += 3
4

julia> x
4

Все версии двоичных арифметических и битовых операторов с присваиванием:

+=  -=  *=  /=  \=  ÷=  %=  ^=  &=  |=  ⊻=  >>>=  >>=  <<=

Оператор с присваиванием переопределяет значение переменной в левой части. В результате возможно изменение типа переменной.

julia> x = 0x01; typeof(x)
UInt8

julia> x *= 2 # Аналогично x = x * 2.
2

julia> typeof(x)
Int64

Векторные операторы с точкой

Для каждой двоичной операции, например для ^, имеется соответствующая операция с точкой .^, определенная автоматически для выполнения ^ поэлементно для каждого значения массива. Например, операция [1,2,3] ^ 3 не определена, так как не существует стандартной математической операции возведения в куб для (неквадратного) массива. Однако определена операция [1,2,3] .^ 3, которая поэлементно вычисляет (векторный) результат [1^3, 2^3, 3^3]. Аналогичным образом, для унарных операторов, таких как ! или , имеется соответствующий оператор с точкой (.√), применяющий операцию для каждого элемента массива.

julia> [1,2,3] .^ 3
3-element Vector{Int64}:
  1
  8
 27

Например, a .^ b анализируется как точечный вызов (^).(a,b), который выполняет операцию трансляции. Эта операция позволяет сочетать массивы со скалярными значениями, сочетать друг с другом массивы одинакового размера (выполняться поэлементно) и даже массивы разных форм (например, сочетать горизонтальные и вертикальные векторы, создавая матрицу). Кроме того, как и все "точечные" вызовы, операторы с точкой являются объединяющими. Например, при вычислении для массива A выражения 2 .* A.^2 .+ sin.(A) (или эквивалентного выражения @. 2A^2 + sin(A) с макросом @.) выполняется один цикл с массивом A, в котором для каждого элемента a из A вычисляется 2a^2 + sin(a). В частности, вложенные точечные вызовы, такие как f.(g.(x)), объединяются, а смежные двоичные операторы, такие как x .+ 3 .* x.^2, эквивалентны вложенным точечным вызовам (+).(x, (*).(3, (^).(x, 2))).

Помимо этого, точечные операторы с присваиванием, такие как a .+= b (или @. a += b), анализируются как a .= a .+ b, где .= представляет собой объединенную операцию присваивания на месте (см. документацию по синтаксису с точкой).

Точечный синтаксис также применим к операторам, определяемым пользователями. Например, если вы определите ⊗(A,B) = kron(A,B), чтобы использовать удобный инфиксный синтаксис A ⊗ B для произведения Кронекера (kron), то [A,B] .⊗ [C,D] будет вычислять [A⊗C, B⊗D] без необходимости написания дополнительного кода.

При сочетании точечных операторов с числовыми литералами может возникать неоднозначность. Например, что означает 1.+x? Это может быть 1. + x или 1 .+ x. Поэтому такой синтаксис не разрешен; в таких случаях нужно ставить вокруг оператора пробелы.

Сравнение чисел

Для всех примитивных числовых типов определены стандартные операции сравнения.

Оператор Название

==

Равенство

!=,

Неравенство

<

Меньше

<=,

Меньше или равно

>

Больше

>=,

Больше или равно

Вот несколько простых примеров.

julia> 1 == 1
true

julia> 1 == 2
false

julia> 1 != 2
true

julia> 1 == 1.0
true

julia> 1 < 2
true

julia> 1.0 > 3
false

julia> 1 >= 1.0
true

julia> -1 <= 1
true

julia> -1 <= -1
true

julia> -1 <= -2
false

julia> 3 < -0.5
false

Целые числа сравниваются стандартно, через сравнение битов. Числа с плавающей запятой сравниваются согласно стандарту IEEE 754:

  • конечные числа упорядочиваются обычным образом;

  • положительный нуль равен отрицательному, но не больше его;

  • значение Inf равно само себе и больше всех других значений, кроме NaN;

  • значение -Inf равно само себе и меньше всех других значений, кроме NaN;

  • значение NaN не равно каким-либо значениям, не больше и не меньше каких-либо значений, включая само это значение.

Последний пункт может быть неожиданным, поэтому имеет смысл отметить следующее.

julia> NaN == NaN
false

julia> NaN != NaN
true

julia> NaN < NaN
false

julia> NaN > NaN
false

Он также может создавать проблемы при работе с массивами.

julia> [1 NaN] == [1 NaN]
false

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

Функция Что проверяет

isequal(x, y)

x и y идентичны.

isfinite(x)

x — конечное число.

isinf(x)

x — бесконечно.

isnan(x)

x не является числом.

isequal расценивает значения NaN как равные друг другу:

julia> isequal(NaN, NaN)
true

julia> isequal([1 NaN], [1 NaN])
true

julia> isequal(NaN, NaN32)
true

isequal также позволяет различать нули со знаком.

julia> -0.0 == 0.0
true

julia> isequal(-0.0, 0.0)
false

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

Для прочих типов isequal по умолчанию вызывает ==, поэтому, если вы хотите определить равенство для собственного типа, просто добавьте для него метод ==. Если вы определяете собственную функцию равенства, имеет смысл определить соответствующий метод hash, чтобы isequal(x,y) подразумевало hash(x) == hash(y).

Цепочка сравнений

В отличие от большинства языков, за немаловажным исключением Python, в Julia возможны произвольные цепочки сравнений.

julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
true

Цепочки сравнений часто бывает удобно использовать в числовом коде. В них применяется оператор && для сравнения скалярных значений и оператор & для поэлементных сравнений, что позволяет использовать в цепочках массивы. Например, 0 .< A .< 1 выдает массив логических значений, элементы которого истинны (true), когда соответствующие элементы A лежат в диапазоне от 0 до 1.

Обратите внимание на порядок работы цепочек сравнений.

julia> v(x) = (println(x); x)
v (generic function with 1 method)

julia> v(1) < v(2) <= v(3)
2
1
3
true

julia> v(1) > v(2) <= v(3)
2
1
false

Выражение посередине вычисляется только один раз, а не два, как было бы при записи выражения в виде v(1) < v(2) && v(2) <= v(3). Однако порядок вычислений в цепочке сравнения является неопределенным. Настоятельно не рекомендуется использовать в них выражения с побочными эффектами (такими как печать). Если эти побочные эффекты необходимы, следует явно использовать оператор && (см. Вычисления по сокращенной схеме).

Элементарные функции

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

Кроме того, эти функции (как и любые функции Julia) могут применяться как векторные для массивов и других коллекций с использованием синтаксиса с точкой f.(A). Например, sin.(A) вычисляет значения синуса для каждого элемента в массиве A.

Приоритет и ассоциативность операторов

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

Категория Операторы Ассоциативность

Синтаксис

. и затем ::

Левая

Возведение в степень

^

Правая

Унарные

+ - √

Правая[1]

Битовый сдвиг

<< >> >>>

Левая

Дроби

//

Левая

Умножение

* / % & \ ÷

Левая[2]

Сложение

+ - | ⊻

Левая[2]

Синтаксис

: ..

Левая

Синтаксис

|>

Левая

Синтаксис

<|

Правая

Сравнение

> < >= <= == === != !== <:

Без ассоциативности

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

&&, затем || и затем ?

Правая

Пара

=>

Правая

Присваивание

= += -= *= /= //= \= ^= ÷= %= |= &= ⊻= <<= >>= >>>=

Правая

Полный перечень приоритетов для каждого оператора Julia см. в верхней части файла src/julia-parser.scm. Учтите, что некоторые из этих операторов не определены в модуле Base, но могут иметь определения в стандартных библиотеках, пакетах или пользовательском коде.

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

julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.)
(11, 12, 17)

julia> Base.operator_precedence(:sin), Base.operator_precedence(:+=), Base.operator_precedence(:(=))  # (Скобки в `:(=)` обязательны.)
(0, 1, 1)

Символьное представление ассоциативности оператора также можно получить, вызвав встроенную функцию Base.operator_associativity.

julia> Base.operator_associativity(:-), Base.operator_associativity(:+), Base.operator_associativity(:^)
(:left, :none, :right)

julia> Base.operator_associativity(:⊗), Base.operator_associativity(:sin), Base.operator_associativity(:→)
(:left, :none, :right)

Примите во внимание, что такие символы, как :sin, возвращают приоритет 0. Это значение представляет недопустимые операторы, а не операторы с наименьшим приоритетом. Аналогичным образом, таким операторам назначается ассоциативность :none.

Числовые литеральные коэффициенты, например 2x, рассматриваются как умножение, выполняемое перед любыми другими двоичными операциями. Исключением является операция возведения в степень (^), при которой умножение будет выполняться в первую очередь, только если оно находится в показателе степени.

julia> x = 3; 2x^2
18

julia> x = 3; 2^2x
64

Их сочетание будет проанализировано как унарный оператор со стандартной асимметрией при возведении в степень: выражения -x^y и 2x^y анализируются как -(x^y) и 2(x^y) соответственно, тогда как x^-y и x^2y анализируются как x^(-y) и x^(2y).

Преобразование типов чисел

Julia поддерживает три варианта преобразования типов чисел, которые отличаются тем, как они обрабатывают неточные преобразования.

  • Запись T(x) или convert(T,x) преобразует x в значение типа T.

    • Если T является типом с плавающей запятой, то результатом будет ближайшее представимое им значение, которое может оказаться положительной или отрицательной бесконечностью.

    • Если тип T является целочисленным, а представить значение x типом T невозможно, то выдается ошибка InexactError.

  • Выражение x % T преобразует целое число x в значение целочисленного типа T, сопоставимое с результатом целочисленного деления x на 2^n, где n — число битов в T. Иными словами, выполняется усечение двоичного представления для соответствия типу.

  • Функции округления принимают тип T в качестве необязательного аргумента. Например, round(Int,x) представляет собой краткую форму записи Int(round(x)).

Различные формы преобразования показаны в следующих примерах.

julia> Int8(127)
127

julia> Int8(128)
ERROR: InexactError: trunc(Int8, 128)
Stacktrace:
[...]

julia> Int8(127.0)
127

julia> Int8(3.14)
ERROR: InexactError: Int8(3.14)
Stacktrace:
[...]

julia> Int8(128.0)
ERROR: InexactError: Int8(128.0)
Stacktrace:
[...]

julia> 127 % Int8
127

julia> 128 % Int8
-128

julia> round(Int8,127.4)
127

julia> round(Int8,127.6)
ERROR: InexactError: trunc(Int8, 128.0)
Stacktrace:
[...]

В разделе Преобразование и продвижение описано, как можно определять собственные преобразования и продвижение.

Функции округления

Функция Описание Тип возвращаемого значения

round(x)

Округляет x до ближайшего целого числа.

typeof(x)

round(T, x)

Округляет x до ближайшего целого числа.

T

floor(x)

Округляет x в направлении -Inf.

typeof(x)

floor(T, x)

Округляет x в направлении -Inf.

T

ceil(x)

Округляет x в направлении +Inf.

typeof(x)

ceil(T, x)

Округляет x в направлении +Inf.

T

trunc(x)

Округляет x в направлении «к нулю».

typeof(x)

trunc(T, x)

Округляет x в направлении «к нулю».

T

Функции деления

Функция Описание

div(x,y), x÷y

Деление с усечением; частное округляется «к нулю».

fld(x,y)

Деление с округлением в меньшую сторону; частное округляется в сторону -Inf.

cld(x,y)

Деление с округлением в большую сторону; частное округляется в сторону +Inf.

rem(x,y), x%y

Остаток; удовлетворяет условию x == div(x,y)*y + rem(x,y); знак соответствует x.

mod(x,y)

Остаток от целочисленного деления; удовлетворяет условию x == fld(x,y)*y + mod(x,y); знак соответствует y.

mod1(x,y)

mod со смещением 1; возвращает r∈(0,y] для y>0 или r∈[y,0) для y<0, где mod(r, y) == mod(x, y).

mod2pi(x)

Остаток от целочисленного деления относительно 2pi; 0 <= mod2pi(x) < 2pi.

divrem(x,y)

Возвращает (div(x,y),rem(x,y)).

fldmod(x,y)

Возвращает (fld(x,y),mod(x,y)).

gcd(x,y...)

Положительный наибольший общий делитель x, y, …​

lcm(x,y...)

Положительное наименьшее общее кратное x, y, …​

Функции знака и абсолютного значения

Функция Описание

abs(x)

Положительное значение, равное по модулю x.

abs2(x)

Модуль x, возведенный в квадрат.

sign(x)

Показывает знак x, возвращая --1, 0 или +1.

signbit(x)

Показывает, включен бит знака (true) или отключен (false).

copysign(x,y)

Значение, равное по модулю x, со знаком y.

flipsign(x,y)

Значение, равное по модулю x, со знаком x*y.

Степени, логарифмы и корни

Функция Описание

sqrt(x), √x

Квадратный корень x.

cbrt(x), ∛x

Кубический корень x.

hypot(x,y)

Гипотенуза прямоугольного треугольника с катетами длиной x и y.

exp(x)

Функция экспоненты с показателем x.

expm1(x)

Точное вычисление exp(x)-1 для x, близких к нулю.

ldexp(x,n)

Эффективное вычисление x*2^n для целых значений n.

log(x)

Натуральный логарифм x.

log(b,x)

Логарифм x по основанию b.

log2(x)

Логарифм x по основанию 2.

log10(x)

Логарифм x по основанию 10.

log1p(x)

Точное вычисление log(1+x) для x, близких к нулю.

exponent(x)

Бинарное возведение в степень для x.

significand(x)

Двоичная значащая часть (мантисса) числа с плавающей запятой x.

Необходимость и полезность таких функций, как hypot, expm1 и log1p, описана в двух превосходных статьях в блоге Джона Кука (John D. Cook): expm1, log1p, erfc и hypot.

Тригонометрические и гиперболические функции

Определены также все стандартные тригонометрические и гиперболические функции.

sin    cos    tan    cot    sec    csc
sinh   cosh   tanh   coth   sech   csch
asin   acos   atan   acot   asec   acsc
asinh  acosh  atanh  acoth  asech  acsch
sinc   cosc

Все они являются функциями одного аргумента, а atan также может принимать два аргумента, соответствуя традиционной функции atan2.

Кроме того, доступны функции sinpi(x) и cospi(x) для более точного вычисления соответственно sin(pi*x) и cos(pi*x).

Для вычисления тригонометрических функций с использованием градусов (а не радиан) добавьте к имени функции окончание d. Например, sind(x) вычисляет синус x, где значение x указано в градусах. Полный список вариантов тригонометрических функций для градусов:

sind   cosd   tand   cotd   secd   cscd
asind  acosd  atand  acotd  asecd  acscd

Специальные функции

Пакет SpecialFunctions.jl содержит множество дополнительных специальных математических функций.


1. Унарные операторы + и - требуют явного наличия скобок вокруг аргумента, чтобы отличить эти операторы от ++ и других. Другие сочетания унарных операторов анализируются с ассоциативностью справа, например √√-a рассматривается как √(√(-a)).
2. Операторы +, ++ и * не имеют ассоциативности. Выражение a + b + c анализируется как +(a, b, c), а не как +(+(a, b), c). Однако резервные методы и для +(a, b, c, d...), и для *(a, b, c, d...) по умолчанию вычисляются с ассоциативностью слева.