Математические операции и элементарные функции
Арифметические операторы
Для всех примитивных числовых типов поддерживаются следующие арифметические операторы.
Выражение | Название | Описание |
---|---|---|
|
Унарный плюс |
Операция тождественности |
|
Унарный минус |
Отображает значения в их аддитивные инверсии. |
|
Двоичный плюс |
Выполняет сложение. |
|
Двоичный минус |
Выполняет вычитание. |
|
Умножение |
Выполняет умножение. |
|
Деление |
Выполняет деление. |
|
Целочисленное деление |
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
поддерживаются следующие логические операторы.
Выражение | Название |
---|---|
|
Отрицание |
|
|
|
Отрицание изменяет true
на false
и наоборот. Пояснения для операций вычисления по сокращенной схеме доступны по приведенным ссылкам.
Обратите внимание, что Bool
представляет собой целочисленный тип и для него также определяются все стандартные правила продвижения и числовые операторы.
Битовые операторы
Для всех примитивных целочисленных типов поддерживаются следующие битовые операторы.
Выражение | Название |
---|---|
|
Битовое «не» |
|
Битовое «и» |
|
Битовое «или» |
|
Битовое исключающее «или» |
|
Битовое «и не» |
|
Битовое «или не» |
|
Логический сдвиг вправо |
|
Арифметический сдвиг вправо |
|
Логический/арифметический сдвиг влево |
Вот ряд примеров использования битовых операторов.
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
Все версии двоичных арифметических и битовых операторов с присваиванием:
+= -= *= /= \= ÷= %= ^= &= |= ⊻= >>>= >>= <<=
Оператор с присваиванием переопределяет значение переменной в левой части. В результате возможно изменение типа переменной.
|
Векторные операторы с точкой
Для каждой двоичной операции, например для ^
, имеется соответствующая операция с точкой .^
, определенная автоматически для выполнения ^
поэлементно для каждого значения массива. Например, операция [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
расценивает значения 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:
[...]
В разделе Преобразование и продвижение описано, как можно определять собственные преобразования и продвижение.
Функции округления
Функция | Описание | Тип возвращаемого значения |
---|---|---|
Округляет |
|
|
Округляет |
|
|
Округляет |
|
|
Округляет |
|
|
Округляет |
|
|
Округляет |
|
|
Округляет |
|
|
Округляет |
|
Функции деления
Функция | Описание |
---|---|
|
Деление с усечением; частное округляется «к нулю». |
Деление с округлением в меньшую сторону; частное округляется в сторону |
|
Деление с округлением в большую сторону; частное округляется в сторону |
|
|
Остаток; удовлетворяет условию |
Остаток от целочисленного деления; удовлетворяет условию |
|
|
|
Остаток от целочисленного деления относительно 2pi; |
|
Возвращает |
|
Возвращает |
|
Положительный наибольший общий делитель |
|
Положительное наименьшее общее кратное |
Функции знака и абсолютного значения
Функция | Описание |
---|---|
Положительное значение, равное по модулю |
|
Модуль |
|
Показывает знак |
|
Показывает, включен бит знака (true) или отключен (false). |
|
Значение, равное по модулю |
|
Значение, равное по модулю |
Степени, логарифмы и корни
Функция | Описание |
---|---|
|
Квадратный корень |
|
Кубический корень |
Гипотенуза прямоугольного треугольника с катетами длиной |
|
Функция экспоненты с показателем |
|
Точное вычисление |
|
Эффективное вычисление |
|
Натуральный логарифм |
|
Логарифм |
|
Логарифм |
|
Логарифм |
|
Точное вычисление |
|
Бинарное возведение в степень для |
|
Двоичная значащая часть (мантисса) числа с плавающей запятой |
Необходимость и полезность таких функций, как 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 содержит множество дополнительных специальных математических функций.
+
и -
требуют явного наличия скобок вокруг аргумента, чтобы отличить эти операторы от ++
и других. Другие сочетания унарных операторов анализируются с ассоциативностью справа, например √√-a
рассматривается как √(√(-a))
.
+
, ++
и *
не имеют ассоциативности. Выражение a + b + c
анализируется как +(a, b, c)
, а не как +(+(a, b), c)
. Однако резервные методы и для +(a, b, c, d...)
, и для *(a, b, c, d...)
по умолчанию вычисляются с ассоциативностью слева.