Complex and rational numbers
We have met the syntax for rational numbers in the previous chapter, and we will review operations on them here. Also, we will introduce another arithmetic type: complex numbers.
Complex numbers
There are two ways to define a complex number in Julia—first, using the Complex
type definition as its associated Complex()
constructor:
# Note the difference in these two definitionsjulia>
c = Complex(1, 2); typeof(c) Complex{Int64}julia>
c = Complex(1, 2.0); typeof(c)Complex{Float64}julia>
c = ComplexF32(1,2.0); typeof(c)Complex{Float32}
Because in the second example, the complex number consists of an ordered pair of two reals, its size is 128 bits, whereas ComplexF32
has 2x Float32
arguments and ComplexF16
will have 2x Float16
arguments.
The Complex(0.0,1.0)
number corresponds to the imaginary number 'I'
—that is, sqrt(-1.0)
—but Julia uses the 'im'
symbol rather than 'I'
to avoid confusion with an I
variable, frequently used as an index iterator.
Hence, Complex(1, 2)
is exactly equivalent to 1 + 2*im
, but normally the '*'
operator is omitted, and this would be expressed as 1 +
2im
.
The complex number supports all normal arithmetic operations, as illustrated here:
julia>
c = 1 + 2im;julia>
d = 3 + 4im;julia>
c*d -5 + 10imjulia>
c/d 0.44 + 0.08imjulia>
c\d 2.2 - 0.4im
The c/d
and c\d
divisions produce real arguments even when the components are integers.
This is like Julia’s behavior with a simple division of integers. Also, it defines real()
, imag()
, conj()
, abs()
, and angle()
complex functions.
abs
and angle
can be used to convert complex arguments to polar form:
julia>
c = 1.0 + 2im; abs(c) 2.23606797749979julia>
angle(c) 1.1071487177940904 # (in radians)
Complex versions of many mathematical functions can be applied:
julia>
c = 1 + 2im;julia>
sin(c) 3.1657 + 1.9596imjulia>
log(c) 0.8047 + 1.10715imjulia>
sqrt(c) 1.272 + 0.78615im
Rationals
Julia has a rational number type to represent exact ratios of integers. A rational is defined by the use of the //
operator—for example, 5//7
. If the numerator and denominator have a common factor, then the number is reduced to its simplest form; for example, 21//35
reduces to 5//7
.
Operations on rationals or on mixed rationals and integers return a rational result:
julia>
x = 3; y = 5//7;julia>
x*y 15//7julia>
y^2 25/49julia>
y/x 5//21
The numerator()
and denominator()
functions return the numerator and denominator of a rational, and float()
can be used to convert a rational to a float:
julia>
x = 17//100;julia>
numerator(x) 17julia>
denominator(x) 100julia>
float(x) => 0.17
Constructing infinite rational values, both positive and negative, is acceptable:
julia>
5//0 1//0julia>
-5//0 -1//0
Notice that both computations reduce the numerator to 1. It is possible to construct rationals of complex numbers, as in this example:
julia>
c = (1 + 2im)//(4 + 3im)
2//5 + 1//5*im
This output is a little confusing as the actual value is (2 + 1im)//5, which arises by multiplying the top and bottom values by the complex conjugate of the denominator (4 – 3im).
The typeof(c)
value is Complex{Rational{Int64}}
, and as of now, the numerator()
and denominator()
functions fail, even though these should return (2 + 1im) and 5 respectively:
julia>
numerator(c)
ERROR: MethodError: no method matching
numerator(::Complex{Rational{Int64}})
Closest candidates are:
numerator(::Integer) at rational.jl:236 numerator(::Rational) at rational.jl:237