# allaxandr's solution

## to Complex Numbers in the Scala Track

Published at Feb 01 2020 · 0 comments
Instructions
Test suite
Solution

A complex number is a number in the form `a + b * i` where `a` and `b` are real and `i` satisfies `i^2 = -1`.

`a` is called the real part and `b` is called the imaginary part of `z`. The conjugate of the number `a + b * i` is the number `a - b * i`. The absolute value of a complex number `z = a + b * i` is a real number `|z| = sqrt(a^2 + b^2)`. The square of the absolute value `|z|^2` is the result of multiplication of `z` by its complex conjugate.

The sum/difference of two complex numbers involves adding/subtracting their real and imaginary parts separately: `(a + i * b) + (c + i * d) = (a + c) + (b + d) * i`, `(a + i * b) - (c + i * d) = (a - c) + (b - d) * i`.

Multiplication result is by definition `(a + i * b) * (c + i * d) = (a * c - b * d) + (b * c + a * d) * i`.

The reciprocal of a non-zero complex number is `1 / (a + i * b) = a/(a^2 + b^2) - b/(a^2 + b^2) * i`.

Dividing a complex number `a + i * b` by another `c + i * d` gives: `(a + i * b) / (c + i * d) = (a * c + b * d)/(c^2 + d^2) + (b * c - a * d)/(c^2 + d^2) * i`.

Raising e to a complex exponent can be expressed as `e^(a + i * b) = e^a * e^(i * b)`, the last term of which is given by Euler's formula `e^(i * b) = cos(b) + i * sin(b)`.

Implement the following operations:

• addition, subtraction, multiplication and division of two complex numbers,
• conjugate, absolute value, exponent of a given complex number.

Assume the programming language you are using does not have an implementation of complex numbers.

The Scala exercises assume an SBT project scheme. The exercise solution source should be placed within the exercise directory/src/main/scala. The exercise unit tests can be found within the exercise directory/src/test/scala.

To run the tests simply run the command `sbt test` in the exercise directory.

Please see the learning and installation pages if you need any help.

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### ComplexNumberTest.scala

``````import org.scalatest.{Matchers, FunSuite}

/** @version 1.3.0 */
class ComplexNumberTest extends FunSuite with Matchers {

private val equalityEpsilon = 1e-15

private def assertEquals(c1: ComplexNumber, c2: ComplexNumber) {
c1.real should be (c2.real +- equalityEpsilon)
c1.imaginary should be (c2.imaginary +- equalityEpsilon)
}

test("Real part of a purely real number") {
ComplexNumber(real = 1).real should be (1.0 +- equalityEpsilon)
}

test("Real part of a purely imaginary number") {
pending
ComplexNumber(real = 0).real should be (0.0 +- equalityEpsilon)
}

test("Real part of a number with real and imaginary part") {
pending
ComplexNumber(real = 1).real should be (1.0 +- equalityEpsilon)
}

test("Imaginary part of a purely real number") {
pending
ComplexNumber(imaginary = 0).imaginary should be (0.0 +- equalityEpsilon)
}

test("Imaginary part of a purely imaginary number") {
pending
ComplexNumber(imaginary = 1).imaginary should be (1.0 +- equalityEpsilon)
}

test("Imaginary part of a number with real and imaginary part") {
pending
ComplexNumber(imaginary = 2).imaginary should be (2.0 +- equalityEpsilon)
}

test("Imaginary unit") {
pending
val result = ComplexNumber(0, 1) * ComplexNumber(0, 1)
assertEquals(result, ComplexNumber(-1, 0))
}

pending
val result = ComplexNumber(1, 0) + ComplexNumber(2, 0)
assertEquals(result, ComplexNumber(3, 0))
}

pending
val result = ComplexNumber(0, 1) + ComplexNumber(0, 2)
assertEquals(result, ComplexNumber(0, 3))
}

test("Add numbers with real and imaginary part") {
pending
val result = ComplexNumber(1, 2) + ComplexNumber(3, 4)
assertEquals(result, ComplexNumber(4, 6))
}

test("Subtract purely real numbers") {
pending
val result = ComplexNumber(1, 0) - ComplexNumber(2, 0)
assertEquals(result, ComplexNumber(-1, 0))
}

test("Subtract purely imaginary numbers") {
pending
val result = ComplexNumber(0, 1) - ComplexNumber(0, 2)
assertEquals(result, ComplexNumber(0, -1))
}

test("Subtract numbers with real and imaginary part") {
pending
val result = ComplexNumber(1, 2) - ComplexNumber(3, 4)
assertEquals(result, ComplexNumber(-2, -2))
}

test("Multiply purely real numbers") {
pending
val result = ComplexNumber(1, 0) * ComplexNumber(2, 0)
assertEquals(result, ComplexNumber(2, 0))
}

test("Multiply purely imaginary numbers") {
pending
val result = ComplexNumber(0, 1) * ComplexNumber(0, 2)
assertEquals(result, ComplexNumber(-2, 0))
}

test("Multiply numbers with real and imaginary part") {
pending
val result = ComplexNumber(1, 2) * ComplexNumber(3, 4)
assertEquals(result, ComplexNumber(-5, 10))
}

test("Divide purely real numbers") {
pending
val result = ComplexNumber(1, 0) / ComplexNumber(2, 0)
assertEquals(result, ComplexNumber(0.5, 0))
}

test("Divide purely imaginary numbers") {
pending
val result = ComplexNumber(0, 1) / ComplexNumber(0, 2)
assertEquals(result, ComplexNumber(0.5, 0))
}

test("Divide numbers with real and imaginary part") {
pending
val result = ComplexNumber(1, 2) / ComplexNumber(3, 4)
assertEquals(result, ComplexNumber(0.44, 0.08))
}

test("Absolute value of a positive purely real number") {
pending
ComplexNumber(5, 0).abs should be (5.0 +- equalityEpsilon)
}

test("Absolute value of a negative purely real number") {
pending
ComplexNumber(-5, 0).abs should be (5.0 +- equalityEpsilon)
}

test("Absolute value of a purely imaginary number with positive imaginary part") {
pending
ComplexNumber(0, 5).abs should be (5.0 +- equalityEpsilon)
}

test("Absolute value of a purely imaginary number with negative imaginary part") {
pending
ComplexNumber(0, -5).abs should be (5.0 +- equalityEpsilon)
}

test("Absolute value of a number with real and imaginary part") {
pending
ComplexNumber(3, 4).abs should be (5.0 +- equalityEpsilon)
}

test("Conjugate a purely real number") {
pending
val result = ComplexNumber(5, 0).conjugate
assertEquals(result, ComplexNumber(5, 0))
}

test("Conjugate a purely imaginary number") {
pending
val result = ComplexNumber(0, 5).conjugate
assertEquals(result, ComplexNumber(0, -5))
}

test("Conjugate a number with real and imaginary part") {
pending
val result = ComplexNumber(1, 1).conjugate
assertEquals(result, ComplexNumber(1, -1))
}

test("Euler's identity/formula") {
pending
val result = ComplexNumber.exp(ComplexNumber(0, math.Pi))
assertEquals(result, ComplexNumber(-1, 0))
}

test("Exponential of 0") {
pending
val result = ComplexNumber.exp(ComplexNumber(0, 0))
assertEquals(result, ComplexNumber(1, 0))
}

test("Exponential of a purely real number") {
pending
val result = ComplexNumber.exp(ComplexNumber(1, 0))
assertEquals(result, ComplexNumber(math.E, 0))
}

test("Exponential of a number with real and imaginary part") {
pending
val result = ComplexNumber.exp(ComplexNumber(math.log(2), math.Pi))
assertEquals(result, ComplexNumber(-2, 0))
}
}``````
``````object ComplexNumber {
import scala.language.implicitConversions
def exp(x: ComplexNumber): ComplexNumber = x.exp
implicit def double2Complex[A <% Double](x: A) = ComplexNumber(x,0)
}

case class ComplexNumber(real: Double = 0, imaginary: Double = 0) {
// unary operators
lazy val abs2:Double = real*real + imaginary*imaginary
lazy val abs: Double = math.sqrt(abs2)
lazy val unary_+ : ComplexNumber = ComplexNumber(real, -imaginary)
lazy val conjugate = unary_+ // a synonym
lazy val unary_- : ComplexNumber = ComplexNumber(-real, -imaginary)
lazy val inverse: ComplexNumber = +this / abs2
lazy val exp: ComplexNumber = math.exp(real) * ComplexNumber(math.cos(imaginary), math.sin(imaginary))
// binary operators with a Double argument
// we need this despite the implicit conversion, as / is expressed through division on a real number
def /(x: Double): ComplexNumber = ComplexNumber(real/x, imaginary/x)
// binary operators
def +(that: ComplexNumber): ComplexNumber = ComplexNumber(real + that.real, imaginary + that.imaginary)
def -(that: ComplexNumber): ComplexNumber = this + (-that)
def *(that: ComplexNumber): ComplexNumber = ComplexNumber(real*that.real - imaginary*that.imaginary, real*that.imaginary + imaginary*that.real)
def /(that: ComplexNumber): ComplexNumber = this * that.inverse
}``````