ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# SergiiVlasiuk's solution

## to Complex Numbers in the Scala Track

Published at Aug 22 2019 · 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`.

Exponent of a complex number can be expressed as `exp(a + i * b) = exp(a) * exp(i * b)`, and the last term is given by Euler's formula `exp(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.

For more detailed info about the Scala track see the help page.

## 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))
}
}``````
``````case class ComplexNumber(real: Double = 0, imaginary: Double = 0) {
def +(that: ComplexNumber): ComplexNumber = ComplexNumber(real + that.real, imaginary + that.imaginary)

def -(that: ComplexNumber): ComplexNumber = ComplexNumber(real - that.real, imaginary - that.imaginary)

def *(that: ComplexNumber): ComplexNumber = ComplexNumber(
real * that.real - imaginary * that.imaginary,
that.real * imaginary + that.imaginary * real
)

def /(that: ComplexNumber): ComplexNumber = ComplexNumber(
(real * that.real + imaginary * that.imaginary) / (that.real * that.real + that.imaginary * that.imaginary),
(imaginary * that.real - real * that.imaginary) / (that.real * that.real + that.imaginary * that.imaginary)
)

def abs: Double = math.sqrt(real * real + imaginary * imaginary)

def conjugate: ComplexNumber = ComplexNumber(real, -imaginary)
}

object ComplexNumber {
def exp(c: ComplexNumber): ComplexNumber = ComplexNumber(
Math.exp(c.real) * Math.cos(c.imaginary),
Math.exp(c.real) * Math.sin(c.imaginary)
)
}``````

### What can you learn from this solution?

A huge amount can be learned from reading other peopleâ€™s code. This is why we wanted to give exercism users the option of making their solutions public.

Here are some questions to help you reflect on this solution and learn the most from it.

• What compromises have been made?