Математические операции и элементарные функции
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 или Julia IDE. Подробнее см. раздел руководства по вводу Юникода.
Вот несколько простых примеров с использованием арифметических операторов:
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 в величинах, которые, как известно, равны нулю. См. Knuth (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 # 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 Vector{Int64}:
1
8
27
Более конкретно, a .^ b интерпретируется как вызов "точки" (^).(a,b), который выполняет операцию распространения: он может сочетать массивы и скаляры, массивы одинакового размера (выполняя операцию поэлементно) и даже массивы разных форм (например, сочетание вектор-строки и вектор-столбца для получения матрицы). Более того, как и все векторизованные вызовы "точки", эти "операторы точки" являются сливаемыми. Например, если вы вычисляете 2 .* A.^2 .+ sin.(A) (или эквивалентно @. 2A^2 + sin(A), используя макрос @.) для массива A, он выполняет один цикл по A, вычисляя 2a^2 + sin(a) для каждого элемента a массива 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> 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(:(=)) # (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.
Коэффициенты числовых литералов, например, 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является целым типом, возникает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) |
деление с округлением вниз; частное округляется к -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) |
логарифм по основанию 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–2022 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors
Licensed under the MIT License.
https://docs.julialang.org/en/v1.8/manual/mathematical-operations/