7.3. Complex numbers

Complex numbers can be created using the global constant im for the imaginary unit \(\sqrt{-1}\):

a = 5 - 3im
5 - 3im

or alternatively using the syntax complex(real,imag):

b = complex(5,3)
5 + 3im
c = 5 + (3/4)im      # Parentheses needed since 3/4im == 3/(4im) 
5.0 + 0.75im

The standard operations work as expected for complex arguments:

a * b
34 + 0im
a / b
0.4705882352941177 - 0.8823529411764706im
(1 + im)^2
0 + 2im

Several functions are provided for manipulation of complex numbers (from the Julia documentation):

julia> z = 1 + 2im
1 + 2im

julia> real(1 + 2im) # real part of z
1

julia> imag(1 + 2im) # imaginary part of z
2

julia> conj(1 + 2im) # complex conjugate of z
1 - 2im

julia> abs(1 + 2im) # absolute value of z
2.23606797749979

julia> abs2(1 + 2im) # squared absolute value
5

julia> angle(1 + 2im) # phase angle in radians
1.1071487177940904

Also most elementary functions are defined for complex arguments (from the Julia documentation):

julia> sqrt(1im)
0.7071067811865476 + 0.7071067811865475im

julia> sqrt(1 + 2im)
1.272019649514069 + 0.7861513777574233im

julia> cos(1 + 2im)
2.0327230070196656 - 3.0518977991518im

julia> exp(1 + 2im)
-1.1312043837568135 + 2.4717266720048188im

julia> sinh(1 + 2im)
-0.4890562590412937 + 1.4031192506220405im

Note that these functions typically return real values when applied to real numbers and complex values when applied to complex numbers:

sqrt(-1.0 + 0im)  # OK, complex input gives complex output
0.0 + 1.0im
sqrt(-1.0)        # Error - real input but needs complex output
DomainError with -1.0:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).

Stacktrace:
 [1] throw_complex_domainerror(f::Symbol, x::Float64)
   @ Base.Math ./math.jl:33
 [2] sqrt(x::Float64)
   @ Base.Math ./math.jl:582
 [3] top-level scope
   @ In[8]:1
 [4] eval
   @ ./boot.jl:360 [inlined]
 [5] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
   @ Base ./loading.jl:1116

7.3.1. Example: Roots of quadratic function

We can now update our previous example of the quadratic formula to handle all cases, including complex roots. We make sure that the argument to the sqrt function is complex:

function roots_of_quadratic(a,b,c)
    # Compute the roots of the quadratic ax^2 + bx + c = 0
    d = sqrt(complex(b^2 - 4*a*c))
    r1 = (-b - d) / 2a
    r2 = (-b + d) / 2a
    r1, r2
end
roots_of_quadratic (generic function with 1 method)
roots_of_quadratic(1,0,1)
(0.0 - 1.0im, 0.0 + 1.0im)
roots_of_quadratic(1,4,13)
(-2.0 - 3.0im, -2.0 + 3.0im)

Note that this implementation will return complex numbers even if the roots are real:

roots_of_quadratic(-1,5,6)
(6.0 + 0.0im, -1.0 - 0.0im)

If desired, one could easily write the function such that it returns real numbers for these cases.