Mathematical Operations and Elementary Functions

Julia предоставляет полный набор основных арифметических и побитовых операторов для всех своих примитивных числовых типов, а также предлагает портативные, эффективные реализации обширной коллекции стандартных математических функций.

Arithmetic Operators

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

ExpressionNameDescription
+xunary plusthe identity operation
-xunary minusmaps values to their additive inverses
x + ybinary plusperforms addition
x - ybinary minusperforms subtraction
x * ytimesperforms multiplication
x / ydivideperforms division
x ÷ yinteger dividex / y, truncated to an integer
x \ yinverse divideequivalent to y / x
x ^ ypowerraises x to the yth power
x % yremainderequivalent to rem(x, y)

Числовой литерал, расположенный непосредственно перед идентификатором или скобками, например, 2x или 2(x + y), рассматривается как умножение, за исключением того, что имеет более высокий приоритет, чем другие бинарные операции. См. Numeric Literal Coefficients для получения подробной информации.

Julia's promotion system makes arithmetic operations on mixtures of argument types "just work" naturally and automatically. See Conversion and Promotion for details of the promotion system.

Знак ÷ можно удобно ввести, написав \div<tab> в REPL или Julia IDE. См. manual section on Unicode input для получения дополнительной информации.

Вот несколько простых примеров с использованием арифметических операторов:

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) для мотивации.

Boolean Operators

Следующие Boolean operators поддерживаются на Bool типах:

ExpressionName
!xnegation
x && yshort-circuiting and
x || yshort-circuiting or

Отрицание изменяет true на false и наоборот. Операции с коротким замыканием объясняются на связанной странице.

Обратите внимание, что Bool является целочисленным типом, и все обычные правила преобразования и числовые операторы также определены для него.

Bitwise Operators

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

ExpressionName
~xbitwise not
x & ybitwise and
x | ybitwise or
x ⊻ ybitwise xor (exclusive or)
x ⊼ ybitwise nand (not and)
x ⊽ ybitwise nor (not or)
x >>> ylogical shift right
x >> yarithmetic shift right
x << ylogical/arithmetic shift left

Вот несколько примеров с побитовыми операторами:

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

Updating operators

Каждый бинарный арифметический и побитовый оператор также имеет обновленную версию, которая присваивает результат операции обратно в свой левый операнд. Обновленная версия бинарного оператора формируется путем размещения = сразу после оператора. Например, запись x += 3 эквивалентна записи x = x + 3:

julia> x = 1
1

julia> x += 3
4

julia> x
4

Обновленные версии всех бинарных арифметических и побитовых операторов:

+=  -=  *=  /=  \=  ÷=  %=  ^=  &=  |=  ⊻=  >>>=  >>=  <<=
Note

Оператор обновления переназначает переменную с левой стороны. В результате тип переменной может измениться.

julia> x = 0x01; typeof(x)
UInt8

julia> x *= 2 # Same as x = x * 2
2

julia> typeof(x)
Int64

Vectorized "dot" operators

Для каждой бинарной операции, такой как ^, существует соответствующая операция "точка" .^, которая автоматически определяется для выполнения ^ поэлементно для массивов. Например, [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 интерпретируется как "dot" call (^).(a,b), что выполняет операцию broadcast: она может комбинировать массивы и скаляры, массивы одинакового размера (выполняя операцию поэлементно) и даже массивы разных форм (например, комбинируя векторы строк и столбцов для получения матрицы). Более того, как и все векторизованные "точечные вызовы", эти "точечные операторы" сливаются. Например, если вы вычисляете 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))).

Furthermore, "dotted" updating operators like a .+= b (or @. a += b) are parsed as a .= a .+ b, where .= is a fused in-place assignment operation (see the dot syntax documentation).

Обратите внимание, что синтаксис с точками также применим к операторам, определяемым пользователем. Например, если вы определите ⊗(A, B) = kron(A, B), чтобы предоставить удобный инфиксный синтаксис A ⊗ B для произведений Кронекера (kron), тогда [A, B] .⊗ [C, D] вычислит [A⊗C, B⊗D] без дополнительного кодирования.

Сочетание операторов точек с числовыми литералами может быть неоднозначным. Например, неясно, означает ли 1.+x 1. + x или 1 .+ x. Поэтому этот синтаксис не допускается, и в таких случаях необходимо использовать пробелы вокруг оператора.

Numeric Comparisons

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

OperatorName
==equality
!=, inequality
<less than
<=, less than or equal to
>greater than
>=, greater than or equal to

Вот несколько простых примеров:

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 standard:

  • Конечные числа упорядочены обычным образом.
  • Положительный ноль равен, но не больше отрицательного нуля.
  • Inf равен самому себе и больше всего, кроме NaN.
  • -Inf равен самому себе и меньше всего остального, кроме NaN.
  • NaN не равен, не меньше и не больше ничего, включая себя.

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

julia> NaN == NaN
false

julia> NaN != NaN
true

julia> NaN < NaN
false

julia> NaN > NaN
false

и может вызывать головные боли при работе с arrays:

julia> [1 NaN] == [1 NaN]
false

Julia предоставляет дополнительные функции для проверки чисел на специальные значения, что может быть полезно в ситуациях, таких как сравнение хеш-ключей:

FunctionTests if
isequal(x, y)x and y are identical
isfinite(x)x is a finite number
isinf(x)x is infinite
isnan(x)x is not a number

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 по умолчанию вызывает ==, поэтому, если вы хотите определить равенство для своих собственных типов, вам нужно только добавить метод 4d61726b646f776e2e436f64652822222c20223d3d2229_40726566. Если вы определяете свою собственную функцию равенства, вам, вероятно, следует определить соответствующий метод hash, чтобы гарантировать, что isequal(x,y) подразумевает hash(x) == hash(y).

Chaining comparisons

В отличие от большинства языков, с notable exception of Python, сравнения могут быть произвольно связаны:

julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
true

Сравнение с цепочками часто бывает довольно удобным в числовом коде. Цепные сравнения используют оператор && для скалярных сравнений и оператор & для поэлементных сравнений, что позволяет им работать с массивами. Например, 0 .< A .< 1 дает булев массив, элементы которого истинны там, где соответствующие элементы 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). Однако порядок вычислений в цепной сравнении не определен. Настоятельно рекомендуется не использовать выражения с побочными эффектами (такими как вывод) в цепных сравнениях. Если побочные эффекты необходимы, оператор короткого замыкания && следует использовать явно (см. Short-Circuit Evaluation).

Elementary Functions

Julia предоставляет обширную коллекцию математических функций и операторов. Эти математические операции определены для как можно более широкого класса числовых значений, для которых допустимы разумные определения, включая целые числа, числа с плавающей запятой, рациональные числа и комплексные числа, где такие определения имеют смысл.

Более того, эти функции (как и любая функция Julia) могут быть применены в "векторизованном" виде к массивам и другим коллекциям с помощью dot syntax f.(A), например, sin.(A) вычислит синус каждого элемента массива A.

Operator Precedence and Associativity

Джулия применяет следующий порядок и ассоциативность операций, от наивысшего приоритета к наименьшему:

CategoryOperatorsAssociativity
Syntax. followed by ::Left
Exponentiation^Right
Unary+ - ! ~ ¬ √ ∛ ∜ ⋆ ± ∓ <: >:Right[1]
Bitshifts<< >> >>>Left
Fractions//Left
Multiplication* / % & \ ÷Left[2]
Addition+ - | ⊻Left[2]
Syntax: ..Left
Syntax|>Left
Syntax<|Right
Comparisons> < >= <= == === != !== <:Non-associative
Control flow&& followed by || followed by ?Right
Pair=>Right
Assignments= += -= *= /= //= \= ^= ÷= %= |= &= ⊻= <<= >>= >>>=Right

Для полного списка всех операторов 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.

Numeric literal coefficients, например, 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).

Numerical Conversions

Julia поддерживает три формы числового преобразования, которые различаются по способу обработки неточных преобразований.

  • Обозначение T(x) или convert(T, x) преобразует x в значение типа T.

    • Если T является типом с плавающей запятой, результатом будет ближайшее представимое значение, которое может быть положительной или отрицательной бесконечностью.
    • Если T является целочисленным типом, возникает ошибка InexactError, если x не может быть представлен в виде T.
  • x % T преобразует целое число x в значение целочисленного типа T, которое эквивалентно x по модулю 2^n, где n — это количество бит в T. Другими словами, двоичное представление обрезается, чтобы соответствовать.

  • Rounding functions принимает тип 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: Int8(128.0)
Stacktrace:
[...]

Смотрите Conversion and Promotion для того, как определить свои собственные преобразования и акции.

Rounding functions

FunctionDescriptionReturn type
round(x)round x to the nearest integertypeof(x)
round(T, x)round x to the nearest integerT
floor(x)round x towards -Inftypeof(x)
floor(T, x)round x towards -InfT
ceil(x)round x towards +Inftypeof(x)
ceil(T, x)round x towards +InfT
trunc(x)round x towards zerotypeof(x)
trunc(T, x)round x towards zeroT

Division functions

FunctionDescription
div(x, y), x÷ytruncated division; quotient rounded towards zero
fld(x, y)floored division; quotient rounded towards -Inf
cld(x, y)ceiling division; quotient rounded towards +Inf
rem(x, y), x%yremainder; satisfies x == div(x, y)*y + rem(x, y); sign matches x
mod(x, y)modulus; satisfies x == fld(x, y)*y + mod(x, y); sign matches y
mod1(x, y)mod with offset 1; returns r∈(0, y] for y>0 or r∈[y, 0) for y<0, where mod(r, y) == mod(x, y)
mod2pi(x)modulus with respect to 2pi; 0 <= mod2pi(x) < 2pi
divrem(x, y)returns (div(x, y),rem(x, y))
fldmod(x, y)returns (fld(x, y), mod(x, y))
gcd(x, y...)greatest positive common divisor of x, y,...
lcm(x, y...)least positive common multiple of x, y,...

Sign and absolute value functions

FunctionDescription
abs(x)a positive value with the magnitude of x
abs2(x)the squared magnitude of x
sign(x)indicates the sign of x, returning -1, 0, or +1
signbit(x)indicates whether the sign bit is on (true) or off (false)
copysign(x, y)a value with the magnitude of x and the sign of y
flipsign(x, y)a value with the magnitude of x and the sign of x*y

Powers, logs and roots

FunctionDescription
sqrt(x), √xsquare root of x
cbrt(x), ∛xcube root of x
hypot(x, y)hypotenuse of right-angled triangle with other sides of length x and y
exp(x)natural exponential function at x
expm1(x)accurate exp(x) - 1 for x near zero
ldexp(x, n)x * 2^n computed efficiently for integer values of n
log(x)natural logarithm of x
log(b, x)base b logarithm of x
log2(x)base 2 logarithm of x
log10(x)base 10 logarithm of x
log1p(x)accurate log(1 + x) for x near zero
exponent(x)binary exponent of x
significand(x)binary significand (a.k.a. mantissa) of a floating-point number x

Для получения обзора того, почему функции, такие как hypot, expm1 и log1p, необходимы и полезны, смотрите отличные посты в блоге Джона Д. Кука на эту тему: expm1, log1p, erfc и hypot.

Trigonometric and hyperbolic functions

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

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

Special functions

Многие другие специальные математические функции предоставляются пакетом SpecialFunctions.jl.

  • 1The unary operators + and - require explicit parentheses around their argument to disambiguate them from the operator ++, etc. Other compositions of unary operators are parsed with right-associativity, e. g., √√-a as √(√(-a)).
  • 2The operators +, ++ and * are non-associative. a + b + c is parsed as +(a, b, c) not +(+(a, b), c). However, the fallback methods for +(a, b, c, d...) and *(a, b, c, d...) both default to left-associative evaluation.