Математические операции и элементарные функции
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)
|
а также отрицание для типов Bool:
| Выражение | Название | Описание |
|---|---|---|
!x |
отрицание | меняет true на false и наоборот |
Числовая литерал, размещенная непосредственно перед идентификатором или скобками, например, 2x или 2(x+y), обрабатывается как умножение, за исключением более высокого приоритета, чем другие бинарные операции. Подробности см. в разделе Коэффициенты числовых литералов.
Система повышения типов Julia делает арифметические операции с комбинациями типов аргументов "работающими" естественным и автоматическим образом. Подробности о системе повышения типов см. в разделе Преобразование и повышение.
Вот несколько простых примеров использования арифметических операторов:
julia> 1 + 2 + 3 6 julia> 1 - 2 -1 julia> 3*2/12 0.5
(По соглашению, мы склонны расположить операторы более плотно, если они применяются перед другими близлежащими операторами. Например, мы обычно писали бы -x + 2 для отражения того, что сначала x отрицается, а затем 2 добавляется к этому результату.)
Побитовые операторы
Следующие побитовые операторы поддерживаются для всех примитивных целочисленных типов:
| Выражение | Название |
|---|---|
~x |
побитовое отрицание |
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> ~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 # Same as 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 Array{Int64,1}:
1
8
27
Более конкретно, a .^ b разбирается как вызов "точка" (^).(a,b), который выполняет операцию распространения: он может объединять массивы и скаляры, массивы одинакового размера (выполняя операцию по элементам) и даже массивы разных форм (например, объединять строчные и столбцовые векторы, чтобы получить матрицу). Более того, как и все векторизованные "вызовы точка", эти "оператор точки" сливаются. Например, если вы вычисляете 2 .* A.^2 .+ sin.(A) (или эквивалентно @. 2A^2 + sin(A), используя макрос @.) для массива A, он выполняет один цикл по A, вычисляя 2a^2 + sin(a) для каждого элемента A. В частности, вложенные вызовы точка сливаются, а "смежные" бинарные операторы, такие как 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> 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
Коэффициенты числовых литералов, например, 2x, обрабатываются как умножения с более высоким приоритетом, чем любая другая бинарная операция, и также имеют более высокий приоритет, чем ^.
Вы также можете найти числовой приоритет любого заданного оператора с помощью встроенной функции 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(:(=)) # (Note the necessary parens on `:(=)`) (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.
Числовые преобразования
Julia поддерживает три формы числовых преобразований, которые различаются по обработке неточных преобразований.
-
Запись
T(x)илиconvert(T,x)преобразуетxв значение типаT.- Если
T— тип с плавающей точкой, результат — ближайшее представимое значение, которое может быть положительной или отрицательной бесконечностью. - Если
T— тип целого числа, возникаетInexactError, еслиxне может быть представлено типомT.
- Если
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) |
деление с округлением вниз; частное округлено к нулю |
cld(x,y) |
деление с округлением вверх; частное округлено к +Inf
|
rem(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) |
логарифм по основанию b от x
|
log2(x) |
логарифм по основанию 2 от x
|
log10(x) |
логарифм по основанию 10 от x
|
log1p(x) |
точное вычисление log(1+x) для x близких к нулю |
exponent(x) |
бинарный показатель x
|
significand(x) |
бинарный мантисса (также известная как мантисса) числа с плавающей запятой x
|
Для ознакомления с причинами необходимости и полезности функций, таких как hypot, expm1 и log1p, обратитесь к отличным блогам Джона Д. Кука по данной теме: 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...)оба по умолчанию используют левоассоциативное вычисление.
© 2009–2020 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors
Licensed under the MIT License.
https://docs.julialang.org/en/v1.4.2/manual/mathematical-operations/