Erlang Central

Difference between revisions of "Complex Numbers"

From ErlangCentral Wiki

(very minor improvement to make/1)
Line 20:Line 20:
 
make(Real, Imaginary) ->
 
make(Real, Imaginary) ->
 
     #complex{real = Real, imaginary = Imaginary}.
 
     #complex{real = Real, imaginary = Imaginary}.
make(Real) ->
+
 
    if
+
make(X) when record(X, complex) -> X;
        is_integer(Real) -> make(Real, 0);
+
make(Real) -> make(Real, 0)).
  is_float(Real)   -> make(Real, 0);
+
  true            -> Real
+
    end.
+
  
 
add(X, Y) ->
 
add(X, Y) ->

Revision as of 13:00, 24 September 2006

Problem

You wish to manipulate complex numbers (i.e., numbers with both a real and imaginary component.) This is commonly needed in engineering, science, and mathematics.

Solution

Unfortunately, Erlang does not come with built-in support for complex numbers. Luckily, we can create our own module to do so.

% Super-primitive Complex Number Implementation
%
-module(complex).
-export([make/2, is_complex/1, add/2, sub/2, mult/2, divide/2,
         get_real/1, get_imaginary/1]).

-record( complex, {real, imaginary}).

is_complex(X) when record(X, complex) -> true;
is_complex(_) -> false.

make(Real, Imaginary) ->
    #complex{real = Real, imaginary = Imaginary}.

make(X) when record(X, complex) -> X;
make(Real) -> make(Real, 0)).

add(X, Y) ->
    A = make(X), B = make(Y),
    make( A#complex.real      + B#complex.real,
          A#complex.imaginary + B#complex.imaginary).

sub(X, Y) ->
    A = make(X), B = make(Y),
    make( A#complex.real      - A#complex.real,
          B#complex.imaginary - B#complex.imaginary).

mult(X, Y) ->
    A = make(X), B = make(Y),
    make( (A#complex.real * B#complex.real)
              - (A#complex.imaginary * B#complex.imaginary),
          (A#complex.real * B#complex.imaginary)
              + (B#complex.real * A#complex.imaginary) ).

divide(X,Y) ->
    A = make(X), B = make(Y),
    Divisor = math:pow(B#complex.real,2) + math:pow(B#complex.imaginary,2),
    make( ((A#complex.real * B#complex.real)
            + (A#complex.imaginary * B#complex.imaginary)) / Divisor,
          ((A#complex.imaginary * B#complex.real)
            - (A#complex.real * B#complex.imaginary)) / Divisor).

get_real(X) -> X#complex.real.

get_imaginary(X) -> X#complex.imaginary.

Here are some examples of this module's use:

1> c(complex).
{ok,complex}
2> A = complex:make(15.0e7,3).
{complex,1.50000e+8,3}
3> B = complex:add(1,Aa).
{complex,1.50000e+8,3}
4> io:format("~.16f~n", [complex:get_real(B)])
150000001.0000000000000000
ok
5> complex:is_complex(Aa).
true
6> C = complex:make(14.0e-4,157.2).
{complex,1.40000e-3,157.200}
7> complex:mult(A,C).
{complex,2.09528e+5,2.35800e+10}
8> io:format("~.16f ~.16fi\n",
8>   [complex:get_real(D),complex:get_imaginary(D)]).
209528.3999999999900000 23580000000.0042000000000000i
ok


This simple module only scratches the surface of what would be required to implement a full module supporting complex arithmetic. For starters, we are missing trigonometric functions, powers, square root, etc.