Avatar of 4d47
0
0
Genius
0
1

4d47's solution

to Complex Numbers in the Clojure Track

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.

Source

Wikipedia https://en.wikipedia.org/wiki/Complex_number

Submitting Incomplete Solutions

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

complex_numbers_test.clj

(ns complex-numbers-test
  (:require [clojure.test :refer [deftest is testing]]
            [complex-numbers :as c]))

;; Tests for Addition
(deftest add-purely-real-numbers
  (testing "Add purely real numbers"
    (is (= (c/add [1 0] [2 0])
           [3 0]))))

(deftest add-purely-imaginary-numbers
  (testing "Add purely imaginary numbers"
    (is (= (c/add [0 1] [0 2])
           [0 3]))))

(deftest add-numbers-with-real-and-imaginary-part
  (testing "Add numbers with real and imaginary part"
    (is (= (c/add [1 2] [3 4])
           [4 6]))))

;; Tests for Subtraction
(deftest subtract-purely-real-numbers
  (testing "Subtract purely real numbers"
    (is (= (c/sub [1 0] [2 0])
           [-1 0]))))

(deftest subtract-purely-imaginary-numbers
  (testing "Subtract purely imaginary numbers"
    (is (= (c/sub [0 1] [0 2])
           [0 -1]))))

(deftest subtract-numbers-with-real-and-imaginary-part
  (testing "Subtract numbers with real and imaginary part"
    (is (= (c/sub [1 2] [3 4])
           [-2 -2]))))

;; Tests for Multiplication
(deftest multiply-purely-real-numbers
  (testing "Multiply purely real numbers"
    (is (= (c/mul [1 0] [2 0])
           [2 0]))))

(deftest multiply-purely-imaginary-numbers
  (testing "Multiply purely imaginary numbers"
    (is (= (c/mul [0 1] [0 2])
           [-2 0]))))

(deftest multiply-numbers-with-real-and-imaginary-part
  (testing "Multiply numbers with real and imaginary part"
    (is (= (c/mul [1 2] [3 4])
           [-5 10]))))

;; Tests for division
(deftest divide-purely-real-numbers
  (testing "Divide purely real numbers"
    (is (= (c/div [1 0] [2 0])
           [0.5 0.0]))))

(deftest dividey-purely-imaginary-numbers
  (testing "Divide purely imaginary numbers"
    (is (= (c/div [0 1] [0 2])
           [0.5 0.0]))))

(deftest divide-numbers-with-real-and-imaginary-part
  (testing "Divide numbers with real and imaginary part"
    (is (= (c/div [1 2] [3 4])
           [0.44 0.08]))))

;; Tests for Absolute Value
(deftest absolute-of-positive-purely-real-number
  (testing "Absolute value of a positive purely real number"
    (is (= (c/abs [5 0])
           5.0))))

(deftest absolute-of-negative-purely-real-number
  (testing "Absolute value of a negative purely real number"
    (is (= (c/abs [-5 0])
           5.0))))

(deftest absolute-of-positive-purely-imaginary-number
  (testing "Absolute value of a purely imaginary number with positive imaginary part"
    (is (= (c/abs [0 5])
           5.0))))

(deftest absolute-of-negative-purely-imaginary-number
  (testing "Absolute value of a purely imaginary number with negative imaginary part"
    (is (= (c/abs [0 -5])
           5.0))))

(deftest absolute-of-real-and-imaginary-number
  (testing "Absolute value of a number with real and imaginary part"
    (is (= (c/abs [3 4])
           5.0))))

;; Tests for Conjugate
(deftest conjugate-of-purely-real-number
  (testing "Conjugate a purely real number"
    (is (= (c/conjugate [5 0])
           [5 0]))))

(deftest conjugate-of-purely-imaginary-number
  (testing "Conjugate a purely imaginary number"
    (is (= (c/conjugate [0 5])
           [0 -5]))))

(deftest conjugate-of-real-and-imaginary-number
  (testing "Conjugate a number with real and imaginary part"
    (is (= (c/conjugate [1 1])
           [1 -1]))))

;; Tests for Real Part
(deftest real-of-purely-real-number
  (testing "Real part of a purely real number"
    (is (= (c/real [1 0])
           1))))

(deftest real-of-purely-imaginary-number
  (testing "Real part of a purely imaginary number"
    (is (= (c/real [0 1])
           0))))

(deftest real-of-real-and-imaginary-number
  (testing "Real part of a number with real and imaginary part"
    (is (= (c/real [1 2])
           1))))

;; Tests for Imaginary Part
(deftest imaginary-of-purely-real-number
  (testing "Imaginary part of a purely real number"
    (is (= (c/imaginary [1 0])
           0))))

(deftest imaginary-of-purely-imaginary-number
  (testing "Imaginary part of a purely imaginary number"
    (is (= (c/imaginary [0 1])
           1))))

(deftest imaginary-of-real-and-imaginary-number
  (testing "Imaginary part of a number with real and imaginary part"
    (is (= (c/imaginary [1 2])
           2))))
(ns complex-numbers)

(defn real [[a b]]
  a)

(defn imaginary [[a b]]
  b)

(defn abs [[a b]]
  (Math/sqrt (+ (Math/pow a 2) (Math/pow b 2))))

(defn conjugate [[a b]]
  [a (- b)])

(defn add [[a b] [c d]]
  [(+ a c) (+ b d)])

(defn sub [[a b] [c d]]
  [(- a c) (- b d)])

(defn mul [[a b] [c d]]
  [(- (* a c) (* b d)) (+ (* b c) (* a d))])

(defn div [[a b] [c d]]
  (let [divisor (+ (Math/pow c 2) (Math/pow d 2))
        r (/ (+ (* a c) (* b d)) divisor)
        i (/ (- (* b c) (* a d)) divisor)]
    [r i]))

What can you learn from this solution?

A huge amount can be learnt 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?
  • Are there new concepts here that I could read more about to develop my understanding?

Community comments

See what others have said about this solution
7 months ago
4d47 says

Avoided the unused argument in real/imaginary because I prefer that arguments of every functions look the same.

Math/pow is used because I think it convey more meaning than (* a a).
Generally tried to avoid anything fancy and just implemented the formulas. eg. I think it's better have a little repeat and leave formula basic than try to name (+ (Math/pow a 2) (Math/pow b 2)