Mathematical Operations and Elementary Functions
Julia предоставляет полный набор основных арифметических и побитовых операторов для всех своих примитивных числовых типов, а также предлагает портативные, эффективные реализации обширной коллекции стандартных математических функций.
Arithmetic Operators
Следующие arithmetic operators поддерживаются для всех примитивных числовых типов:
Expression | Name | Description |
---|---|---|
+x | unary plus | the identity operation |
-x | unary minus | maps values to their additive inverses |
x + y | binary plus | performs addition |
x - y | binary minus | performs subtraction |
x * y | times | performs multiplication |
x / y | divide | performs division |
x ÷ y | integer divide | x / y, truncated to an integer |
x \ y | inverse divide | equivalent to y / x |
x ^ y | power | raises x to the y th power |
x % y | remainder | equivalent 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
типах:
Expression | Name |
---|---|
!x | negation |
x && y | short-circuiting and |
x || y | short-circuiting or |
Отрицание изменяет true
на false
и наоборот. Операции с коротким замыканием объясняются на связанной странице.
Обратите внимание, что Bool
является целочисленным типом, и все обычные правила преобразования и числовые операторы также определены для него.
Bitwise Operators
Следующие bitwise operators поддерживаются для всех примитивных целочисленных типов:
Expression | Name |
---|---|
~x | bitwise not |
x & y | bitwise and |
x | y | bitwise or |
x ⊻ y | bitwise xor (exclusive or) |
x ⊼ y | bitwise nand (not and) |
x ⊽ y | bitwise nor (not or) |
x >>> y | logical shift right |
x >> y | arithmetic shift right |
x << y | logical/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
Обновленные версии всех бинарных арифметических и побитовых операторов:
+= -= *= /= \= ÷= %= ^= &= |= ⊻= >>>= >>= <<=
Оператор обновления переназначает переменную с левой стороны. В результате тип переменной может измениться.
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
Стандартные операции сравнения определены для всех примитивных числовых типов:
Operator | Name |
---|---|
== | 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 предоставляет дополнительные функции для проверки чисел на специальные значения, что может быть полезно в ситуациях, таких как сравнение хеш-ключей:
Function | Tests 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
Джулия применяет следующий порядок и ассоциативность операций, от наивысшего приоритета к наименьшему:
Category | Operators | Associativity |
---|---|---|
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
Function | Description | Return type |
---|---|---|
round(x) | round x to the nearest integer | typeof(x) |
round(T, x) | round x to the nearest integer | T |
floor(x) | round x towards -Inf | typeof(x) |
floor(T, x) | round x towards -Inf | T |
ceil(x) | round x towards +Inf | typeof(x) |
ceil(T, x) | round x towards +Inf | T |
trunc(x) | round x towards zero | typeof(x) |
trunc(T, x) | round x towards zero | T |
Division functions
Function | Description |
---|---|
div(x, y) , x÷y | truncated 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%y | remainder; 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
Function | Description |
---|---|
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
Function | Description |
---|---|
sqrt(x) , √x | square root of x |
cbrt(x) , ∛x | cube 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.