Mathematical operations and elementary functions
Arithmetic operators
The following are supported for all primitive numeric types https://en.wikipedia.org/wiki/Arithmetic#Arithmetic_operations [arithmetic operators].
Expression | Name | Description |
---|---|---|
|
The unary plus |
The identity operation |
|
Unary minus sign |
Displays values in their additive inversions |
|
Binary Plus |
Performs addition |
|
Binary negative |
Performs subtraction |
|
Multiplication |
Performs multiplication |
|
Division |
Performs division |
|
Integer division |
x /y rounded to an integer |
|
Division with inversion |
Equivalent to |
|
Exponentiation |
Raises |
|
Remains |
Equivalent to |
Putting a numeric literal directly in front of an identifier or parentheses, such as 2x
or 2(x + y)
, is considered a multiplication, and with a higher priority than other binary operations. For more information: see Numeric literal coefficients.
Thanks to the Julia promotion system, arithmetic operations on combinations of different types of arguments are performed automatically, naturally, and intuitively. For more information about this system, see Transformation and promotion.
You can use \div<tab>
in the REPL or the Julia IDE to conveniently enter the sign. For more information: see section of the guide on entering Unicode characters.
Here are some simple examples of using arithmetic operators.
julia> 1 + 2 + 3
6
julia> 1 - 2
-1
julia> 3*2/12
0.5
(By convention, operators executed earlier than other nearby operators are separated by a shorter distance. For example, writing -x + 2
usually means that x
is accessed first, and then 2
is added to the result.)
When used in multiplication, the value `false' acts as a _ strong zero_.
julia> NaN * false
0.0
julia> false * Inf
0.0
This prevents the substitution of NaN
values in obviously zero amounts. The rationale: https://arxiv.org/abs/math/9205211 [Knut (1992)].
Logical operators
For types Bool
the following are supported https://en.wikipedia.org/wiki/Boolean_algebra#Operations [logical operators].
Expression | Name |
---|---|
|
Denial |
|
|
|
Negation changes true
to `false', and vice versa. Explanations for the calculation operations according to the abbreviated scheme are available at the links provided.
Note that Bool
is an integer type and all the standard promotion rules and numeric operators are defined for it as well.
Bitwise operators
For all primitive integer types, the following are supported https://en.wikipedia.org/wiki/Bitwise_operation#Bitwise_operators [bitwise operators].
Expression | Name |
---|---|
|
Bitwise "not" |
|
Bitwise "and" |
|
Bitwise "or" |
|
The bit-exclusive "or" |
|
Bitwise "and not" |
|
Bitwise "or not" |
|
Logical shift to the right |
|
Arithmetic shift to the right |
|
Logical/Arithmetic left shift |
Here are some examples of using bitwise operators.
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
Assignment operators
All binary arithmetic and bitwise operators also have an assignment version that passes the result to the operand on the left. To use the assignment version of the binary operator, you must specify the =
sign immediately after the operator. For example, the entry x += 3
is equivalent to `x = x + 3'.
julia> x = 1
1
julia> x += 3
4
julia> x
4
All versions of binary arithmetic and bit assignment operators:
+= -= *= /= \= ÷= %= ^= &= |= ⊻= >>>= >>= <<=
The assignment operator overrides the value of the variable on the left side. As a result, it is possible to change the type of the variable.
|
Vector operators with a dot
For every binary operation like ^
, there is a corresponding "dot" operation .^
that is automatically defined to perform ^
element-by-element on arrays. For example, [1, 2, 3] ^ 3
is not defined, since there is no standard mathematical meaning to "cubing" a (non-square) array, but [1, 2, 3] .^ 3
is defined as computing the elementwise (or "vectorized") result [1^3, 2^3, 3^3]
. Similarly for unary operators like !
or √
, there is a corresponding .√
that applies the operator elementwise.
julia> [1, 2, 3] .^ 3
3-element Vector{Int64}:
1
8
27
For example, a .^ b
is analyzed as dot call (^).(a,b)
, which performs the operation broadcasts. This operation allows you to combine arrays with scalar values, combine arrays of the same size with each other (performed element by element), and even arrays of different shapes (for example, horizontal and vertical vectors, creating a matrix). In addition, like all "dot" calls, dot operators are connecting. For example, when calculating the expression +2 .* A.^2 .+ sin for the array `A
.(A)` (or the equivalent expression `@. 2A^2 + sin(A)` with a macro xref:base/arrays.adoc#Base.Broadcast.@__dot__[`@.`]) a single loop is executed with the array `A`, in which `+2a^2 + sin(a)` is calculated for each element a
from A
. In particular, nested dot calls such as f.(g.(x))
are combined, and adjacent binary operators such as x .+3 .*x.^2
are equivalent to nested dot calls (+).(x, (*).(3, (^).( x, 2)))
.
In addition, dot operators with assignment, such as a .+= b
(or @. a += b
), are analyzed as a .= a .+ b
, where .=
represents the combined operation of assigning _ to a place (see documentation on syntax with a dot).
The dot syntax is also applicable to user-defined operators. For example, if you define ⊗(A, B) = kron(A, B)
to use the convenient infix syntax A ⊗ B
for the Kronecker product (kron
), then [A, B] .⊗ [C, D]
will calculate [A⊗C, B⊗D]
without the need to write additional code.
When dot operators are combined with numeric literals, ambiguity may occur. For example, what does 1.+x
mean? It could be 1. + x
or 1 .+ x
. Therefore, this syntax is not allowed; in such cases, you need to put spaces around the operator.
Comparing numbers
Standard comparison operations are defined for all primitive numeric types.
Operator | Name |
---|---|
Equality |
|
Inequality |
|
Less |
|
Less than or equal to |
|
More |
|
Greater than or equal to |
Here are some simple examples.
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
Integers are compared using the standard bit comparison. Floating point numbers are compared according to https://en.wikipedia.org/wiki/IEEE_754-2008 [IEEE 754 standard]:
-
the final numbers are ordered in the usual way;
-
a positive zero is equal to a negative one, but not greater than it;
-
the value of
Inf
is equal to itself and greater than all other values exceptNaN
; -
the value of
-Inf
is equal to itself and smaller than all other values exceptNaN
; -
the value of
NaN
is not equal to any values, not more or less than any values, including this value itself.
The last point may be unexpected, so it makes sense to note the following.
julia> NaN == NaN
false
julia> NaN != NaN
true
julia> NaN < NaN
false
julia> NaN > NaN
false
It can also create problems when working with arrays.
julia> [1 NaN] == [1 NaN]
false
Additional functions are available in Julia to check special values of numbers, which can be useful, for example, when comparing a hash key.
Function | What checks |
---|---|
The 'x` and |
|
'x` is a finite number. |
|
'x' is infinite. |
|
'x` is not a number. |
isequal
evaluates the values of NaN
as equals to each other:
julia> isequal(NaN, NaN)
true
julia> isequal([1 NaN], [1 NaN])
true
julia> isequal(NaN, NaN32)
true
'isequal` also allows you to distinguish between signed zeros.
julia> -0.0 == 0.0
true
julia> isequal(-0.0, 0.0)
false
Comparing different types of values when comparing signed, unsigned, and floating-point integers is often difficult. Significant efforts have been made to ensure that they are executed correctly in Julia.
For other types, isequal
calls by default ==
, so if you want to define equality for your own type, just add a method for it. ==
. If you are defining your own equality function, it makes sense to define an appropriate method. hash
so that isequal(x,y)
implies `hash(x) == hash(y)'.
A chain of comparisons
Unlike most languages, https://en.wikipedia.org/wiki/Python_syntax_and_semantics#Comparison_operators [with the notable exception of Python], arbitrary comparison chains are possible in Julia.
julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
true
Comparison chains are often convenient to use in numeric code. They use the &&
operator to compare scalar values and the operator &
for element-by-element comparisons, which allows arrays to be used in chains. For example, 0 .< A .< 1
outputs an array of boolean values, the elements of which are true when the corresponding elements of A
are in the range from 0 to 1.
Pay attention to the order in which the comparison chains work.
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
The expression in the middle is evaluated only once, not twice, as it would be when writing an expression in the form v(1) < v(2) && v(2) <= v(3)
. However, the order of calculations in the comparison chain is uncertain. It is strongly discouraged to use expressions with side effects (such as printing) in them. If these side effects are necessary, you should explicitly use the '&&` operator (see Calculations according to an abbreviated scheme).
Elementary functions
A comprehensive set of mathematical functions and operators is available in Julia. These mathematical operations are defined for the widest possible class of numeric values for which they make sense, including integers, floating-point numbers, rational and complex numbers.
In addition, these functions (like any Julia functions) can be used as vector functions for arrays and other collections using syntax with a dot f.(A)
. For example, sin.(A)
calculates the sine values for each element in the array `A'.
Operator precedence and associativity
The Julia language uses the following order and associativity of operators, from the highest priority to the lowest.
Category | Operators | Associativity |
---|---|---|
Syntax |
|
Lefthand |
Exponentiation |
|
The right one |
Unary |
|
Right Footnote:1[The unary operators |
Bit shift |
|
Lefthand |
Fractions |
|
Lefthand |
Multiplication |
|
Left Footnote:2[The operators |
Addition |
|
Left Footnote:2[] |
Syntax |
|
Lefthand |
Syntax |
|
Lefthand |
Syntax |
|
The right one |
Comparison |
|
Without associativity |
The order of execution |
'&&`, then |
The right one |
Couple |
|
The right one |
Assignment |
|
The right one |
For a complete list of priorities for each Julia operator, see at the top of the file: https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm [src/julia-parser.scm
]. Note that some of these operators are not defined in the Base module, but may have definitions in standard libraries, packages, or user code.
You can also find out the numerical priority value of any operator using the built-in function Base.operator_precedence
(the higher the number, the higher the priority).
julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.)
(11, 12, 17)
julia> Base.operator_precedence(:sin), Base.operator_precedence(:+=), Base.operator_precedence(:(=)) # (Скобки в `:(=)` обязательны.)
(0, 1, 1)
A symbolic representation of operator associativity can also be obtained by calling the built-in function `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)
Please note that characters such as :sin
return the priority of `0'. This value represents invalid operators, not operators with the lowest priority. Similarly, such operators are assigned the associativity `:none'.
Numeric literal coefficients, such as 2x', are treated as multiplication performed before any other binary operations. The exception is the exponentiation operation (
^`), in which multiplication will be performed first only if it is in the exponent.
julia> x = 3; 2x^2
18
julia> x = 3; 2^2x
64
Their combination will be analyzed as a unary operator with standard asymmetry during exponentiation: the expressions -x^y
and 2x^y
are analyzed as -(x^y)
and 2(x^y)
respectively, whereas x^-y
and x^2y
are analyzed as x^(-y)
and `x^(2y)'.
Number Type Conversion
Julia supports three number type conversion options, which differ in how they handle inaccurate conversions.
-
Writing
T(x)
orconvert(T, x)
convertsx
to a value of type `T'.-
If
T
is a floating-point type, the result will be the nearest value it represents, which can be a positive or negative infinity. -
If the type
T
is an integer, and the valuex
cannot be represented by the typeT
, the errorInexactError
is returned.
-
-
'x%T` converts an integer
x
into an integer type valueT
, comparable to the result of integer division ofx
by2^n
, wheren
is the number of bits inT
. In other words, the binary representation is truncated to match the type. -
Rounding functions take the type
T
as an optional argument. For example,round(Int,x)
is a short form ofInt(round(x))'.
.
The various forms of conversion are shown in the following examples.
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:
[...]
In the section Transformation and Promotion describes how you can define your own transformations and promotions.
Rounding functions
Function | Description | The type of the returned value |
---|---|---|
Rounds |
|
|
Rounds |
|
|
Rounds the |
|
|
Rounds the |
|
|
Rounds |
|
|
Rounds |
|
|
Rounds the |
|
|
Rounds the |
|
Division functions
Function | Description |
---|---|
|
Division with truncation; the quotient is rounded "to zero" |
Division rounded down; quotient rounded towards |
|
Up-rounded division; the quotient is rounded towards |
|
|
Remainder; satisfies the condition |
Remainder of integer division; satisfies the condition |
|
|
|
Remainder of integer division relative to 2pi; |
|
Returns |
|
Returns |
|
The positive greatest common divisor is |
|
The positive smallest common multiple of |
Sign and absolute value functions
Function | Description |
---|---|
A positive value modulo |
|
The module `x' squared |
|
Shows the 'x` sign, returning --1, 0 or +1 |
|
Indicates whether the sign bit is enabled (true) or disabled (false) |
|
A value modulo |
|
A value modulo |
Degrees, logarithms, and roots
Function | Description |
---|---|
|
The square root of |
|
The cubic root of |
Hypotenuse of a right triangle with legs of length |
|
Exponent function with exponent |
|
Exact calculation of |
|
Efficient calculation of |
|
The natural logarithm of `x'. |
|
The logarithm of |
|
The logarithm of 'x` in base 2 |
|
The logarithm of 'x` in base 10 |
|
Exact calculation of |
|
Binary exponentiation for |
|
The binary significant part (mantissa) of a floating-point number |
The necessity and usefulness of functions such as hypot
, expm1
and log1p
, described in two excellent articles on John D. Cook’s blog: https://www.johndcook.com/blog/2010/06/07/math-library-functions-that-seem-unnecessary /[expm1, log1p, erfc] and https://www.johndcook.com/blog/2010/06/02/whats-so-hard-about-finding-a-hypotenuse /[hypot].
Trigonometric and hyperbolic functions
All standard trigonometric and hyperbolic functions are also defined.
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
They are all functions of a single argument, and atan
can also take two arguments, corresponding to the traditional function https://en.wikipedia.org/wiki/Atan2 [atan2
].
In addition, functions are available sinpi(x)
and cospi(x)
for a more accurate calculation, respectively sin(pi * x)
and cos(pi * x)
.
To calculate trigonometric functions using degrees (rather than radians), add the ending d
to the function name. For example, sind(x)
calculates the sine of x
, where the value of x
is given in degrees. A complete list of options for trigonometric functions for degrees:
sind cosd tand cotd secd cscd asind acosd atand acotd asecd acscd
Special functions
Package https://github.com/JuliaMath/SpecialFunctions.jl [SpecialFunctions.jl] contains many additional special mathematical functions.