Arithmetic operators
Basic arithmetic operations are defined in Julia standard libraries, and all these operators are supported on all primitive numeric types
| Expression | Name | Description |
|---|---|---|
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 yth power |
x % y | remainder | equivalent to rem(x,y) |
Here are some simple examples using arithmetic operators
julia> 1 + 2
3
julia> 2*3
6
julia> 4/3
1.3333333333333333All of these operators can also be applied directly to any variable that represents a numeric value
julia> x = 1;
julia> y = 3;
julia> (x + 2)/(y - 1) - 4*(x - 2)^2
-2.5Note that we use a semicolon after some expressions. In the REPL, if we evaluate any expression, its result is printed. If we use the semicolon, the output is omitted. It is similar behaviour as in Matlab, but in Julia, the printing is automatic only in the REPL.
A numeric literal placed directly before an identifier or parentheses is treated as multiplication
julia> 2(3 + 4) # equivalent to 2*(3 + 4)
14Determine the value and type of y given by the following expression
\[y = \frac{(x + 2)^2 - 4}{(x - 2)^{p - 2}},\]
where x = 4 and p = 5.
Solution:
First, we define variables x and p
julia> x = 4
4
julia> p = 5
5then we can use the combination of basic arithmetic operators to compute the value of y
julia> y = ((x + 2)^2 - 4)/(x - 2)^(p - 2)
4.0The type of y can be determined using the typeof function
julia> typeof(y)
Float64Note that the resulting type of y is Float64 even though the result can be represented as an integer. The reason is that we divide two integers
julia> typeof((x + 2)^2 - 4)
Int64
julia> typeof((x - 2)^(p - 2))
Int64Because this operation generally does not result in an integer, dividing two integers always returns a floating-point number. If we want to get an integer, we can use the integer division operator ÷ (can be typed as \div<tab>)
julia> y_int = ((x + 2)^2 - 4)÷(x - 2)^(p - 2)
4
julia> typeof(y_int)
Int64Promotion system
The section about variables showed that there are many numeric types in Julia. To ensure that the correct type is always used, Julia has a promotion system that converts input values of mixed types to a type that can correctly represent all values. The promotion of mixed type variables can be done manually using the promote function. As an example, we can mention the promotion of multiple numeric types
julia> x = 1.0 # Float64
1.0
julia> y = 2 # Int64
2
julia> xp, yp = promote(x, y)
(1.0, 2.0)In this case, the resulting type of variables xp and yp is Float64 as can be checked using the typeof function
julia> typeof(xp)
Float64
julia> typeof(yp)
Float64Strictly speaking, not all Int64 values can be represented exactly as Float64 values. The promotion system generally tries to return a type that approximates well most values of either input type.
The promote function accepts any number of input arguments
julia> promote(1, 2f0, true, 4.5, Int32(1))
(1.0, 2.0, 1.0, 4.5, 1.0)The resulting type of promotion can be determined by the promotion_type function. This function is similar to the promote function and will accept any number of input arguments, but the inputs have to be types and not values
julia> promote_type(Float64, Int64, Bool, Int32)
Float64Although this may seem complicated, type promotion is done automatically in most cases, and the user does not have to worry about it. To demonstrate the promotion system in practice, consider the following example: we sum the value of type Int64 with the value of type Float32
julia> x = 1 # Int64
1
julia> y = 2f0 # Float32
2.0f0Since the "smallest" type that can represent both values correctly is Float32, the result is of type Float32
julia> z = x + y
3.0f0
julia> typeof(z)
Float32All of these values represent number $1$. Determine the smallest type which can represent them.
x = 1
y = 1f0
z = true
w = Int32(1)Solution:
To get the correct promotion type, we can use a combination of the promote and typeof functions
julia> xp, yp, zp, wp = promote(x, y, z, w)
(1.0f0, 1.0f0, 1.0f0, 1.0f0)
julia> typeof(xp)
Float32or the promote_type and typeof functions
julia> promote_type(typeof(x), typeof(y), typeof(z), typeof(w))
Float32Updating operators
Every binary arithmetic operator also has an updating version that assigns the operation's result back into its left operand. The updating version of the binary operator is formed by placing a = symbol immediately after the operator. For example, writing x += 3 is equivalent to writing x = x + 3
julia> x = 1
1
julia> x += 3 # x = x + 3
4
julia> x *= 4 # x = x * 4
16
julia> x /= 2 # x = x / 2
8.0
julia> x \= 16 # x = x \ 16 = 16 / x
2.0Compute the value of y given by the following expression
\[y = \frac{(x + 4)^{\frac{3}{2}}}{(x + 1)^{p - 1}},\]
where x = 5 and p = 3. Then multiply the result by 8, add 3, divide by 3, and subtract 1. What are all the intermediate results and the final result?
Solution:
First, we calculate the value of y
julia> x = 5;
julia> p = 3;
julia> y = (x + 4)^(3/2)/(x + 1)^(p - 1)
0.75Then we can use the update operators to get all the intermediate results as well as the final result
julia> y *= 8
6.0
julia> y += 3
9.0
julia> y /= 3
3.0
julia> y -= 1
2.0Numeric comparison
In addition to arithmetic and updating operators, basic comparison operators are also defined in Julia's standard libraries.
| Operator | Name |
|---|---|
== | equality |
!=, ≠ | inequality |
< | less than |
<=, ≤ | less than or equal to |
> | greater than |
>=, ≥ | greater than or equal to |
& | bitwise and |
| | bitwise or |
All these operators always return a boolean value (true or false) as the following example shows
julia> 1 == 1
true
julia> 1 == 1.0
true
julia> -1 <= 1
true
julia> -1 ≥ 1
falseIn most programming languages, comparison operators are strictly binary, i.e., they can be used to compare only two values at a time. As an example, we can use a comparison of three numbers in Matlab
>> 3 > 2 > 1
ans =
logical
0Even though the condition holds, the result is false (logical 0). The correct way to write such a condition in Matlab is as follows
>> 3 > 2 & 2 > 1
ans =
logical
1In Julia (and Python, for example), both ways of writing conditions are correct and lead to the same result
julia> 3 > 2 > 1
true
julia> 3 > 2 & 2 > 1
trueIn fact, comparison operators can be arbitrarily chained as in the following example
julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
trueIn general, the user should always try to write code that is easy to read. Even though writing expressions as in the example above is possible, the user should always consider if it is necessary.
Comparison of special values such as NaN can lead to unexpected behaviour
julia> NaN == NaN
false
julia> NaN != NaN
true
julia> NaN < NaN
falseTo avoid unexpected result, Julia provides additional functions to compare numbers for special values
| 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 |
Function isequal considers NaNs equal to each other
julia> isequal(NaN, NaN)
true
julia> !isequal(NaN, NaN)
falseWe used the operator ! to negate the output of the isequal function in the example above. This operator is called boolean not and can be used to negate boolean values
julia> !true
false
julia> !false
trueRounding functions
Julia provides several functions for rounding numbers, as can be seen in the following table
| Function | Description |
|---|---|
round(x) | round x to the nearest integer |
floor(x) | round x towards -Inf |
ceil(x) | round x towards +Inf |
trunc(x) | round x towards zero |
These functions can be used without specifying output types. In such a case, the output has the same type as the input variable
julia> x = 3141.5926
3141.5926
julia> round(x)
3142.0
julia> floor(x)
3141.0
julia> ceil(x)
3142.0However, in many cases, it makes sense to convert the rounded value to a different type. For example, if the rounded value can be represented as an integer, it makes sense to convert the rounded value to an integer. The output type (only subtypes of Integer with the exception of Bool) can be passed as the first argument to all rounding functions from the table above
julia> round(Int64, x)
3142
julia> floor(Int32, x)
3141
julia> ceil(Int16, x)
3142All rounding functions also support additional keyword arguments:
- If the
digitskeyword argument is provided, it rounds to the specified number of digits after the decimal place in the base specified by thebasekeyword argument.
julia> round(x; digits = 3)
3141.593- If the
sigdigitskeyword argument is provided, it rounds to the specified number of significant digits in the base specified by thebasekeyword argument.
julia> round(x; sigdigits = 3)
3140.0Use rounding functions to solve the following tasks:
- Round
1252.1518to the nearest larger integer and convert the resulting value toInt64. - Round
1252.1518to the nearest smaller integer and convert the resulting value toInt16. - Round
1252.1518to2digits after the decimal point. - Round
1252.1518to3significant digits.
Solution:
The ceil function rounds numbers to the nearest larger value, and since we want the result to be of type Int64, we have to pass this type as a first argument
julia> x = 1252.1518
1252.1518
julia> ceil(Int64, x)
1253Similarly, the floor function rounds numbers to the nearest smaller value
julia> floor(Int16, x)
1252The number of digits after the decimal point can be controlled using the digits keyword
julia> round(x; digits = 2)
1252.15and the number of significant digits using the sigdigits keyword
julia> round(x; sigdigits = 3)
1250.0Numerical conversions
The previous section showed that numerical conversions could be done by using rounding functions with a specified type of output variable. This works only for converting floating-point numbers to integers. Julia also provides a more general way of how to perform conversions between different (not only numerical) types: notation T(x) or convert(T,x) converts x to a value of type T.
- If
Tis a floating-point type, the result is the nearest representable value, which could be positive or negative infinity
julia> convert(Float32, 1.234)
1.234f0
julia> Float32(1.234)
1.234f0- If
Tis an integer type, anInexactErroris raised ifxis not representable byT
julia> convert(Int64, 1.0)
1
julia> Int64(1.0)
1
julia> convert(Int64, 1.234)
ERROR: InexactError: Int64(1.234)
[...]
julia> Int64(1.234)
ERROR: InexactError: Int64(1.234)
[...]Conversion to other types works in a similar way.
Use the proper numeric conversion to get the correct result (not approximate) of summing the following two numbers
x = 1//3
y = 0.5Hint: rational numbers can be summed without approximation.
Solution:
Firstly, we can try just to sum the given numbers
julia> x + y
0.8333333333333333The result of this operation is a floating-point number. However, in this specific case, we have a rational number and a floating-point number that can also be represented as a rational number. The exact result can be obtained by converting the variable y to a rational number
julia> x + Rational(y)
5//6