Математические операции и элементарные функции
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 вниз до ближайшего целого
|
typeof(x) |
floor(T, x) |
округление x вниз до ближайшего целого
|
T |
ceil(x) |
округление x вверх до ближайшего целого
|
typeof(x) |
ceil(T, x) |
округление x вверх до ближайшего целого
|
T |
trunc(x) |
округление x к нулю |
typeof(x) |
trunc(T, x) |
округление x к нулю |
T |
Функции деления
| Функция | Описание |
|---|---|
div(x,y), x÷y
|
усечённое деление; частное округляется к нулю |
fld(x,y) |
целочисленное деление, частное округляется к нулю |
cld(x,y) |
наибольшее целочисленное деление, частное округляется вверх |
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) |
модуль относительно 2π; 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.
Кроме того, для более точных вычислений sin(pi*x) и cos(pi*x) соответственно предоставляются sinpi(x) и cospi(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–2021 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors
Licensed under the MIT License.
https://docs.julialang.org/en/v1.7.0/manual/mathematical-operations/