Spec-Zone.ru › Julia 1.5

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

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 добавляется к этому результату.)

При использовании в умножении false действует как сильный ноль:

julia> NaN * false
0.0

julia> false * Inf
0.0

Это полезно для предотвращения распространения NaN значений в величинах, которые, как известно, равны нулю. См. Knuth (1992) здесь для мотивации.

Побитовые операторы

Следующие побитовые операторы поддерживаются для всех примитивных целочисленных типов:

Выражение Название
~x побитовое отрицание
x & y побитовое И
x | y побитовое ИЛИ
x ⊻ y побитовое исключающее ИЛИ (XOR)
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. В частности, вложенные вызовы «точки», такие как 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

Коэффициенты числовых литералов, например, 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) деление с округлением вниз; частное округляется к -Inf
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.5.3/manual/mathematical-operations/

Spec-Zone.ru

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