Spec-Zone.ru › Julia 1.7

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

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.

END_OF_DOCUMENT_MARKER

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

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

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/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API