Avatar of tqa236

tqa236's solution

to Complex Numbers in the Java Track

Published at Oct 19 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.

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.

Running the tests

You can run all the tests for an exercise by entering

$ gradle test

in your terminal.

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.

ComplexNumberTest.java

import org.junit.Ignore;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class ComplexNumberTest {

    // Test helpers

    private static final double DOUBLE_EQUALITY_TOLERANCE = 1e-15;

    private void assertDoublesEqual(double d1, double d2, String numberPart) {
        String errorMessage = "While testing " + numberPart + " part of number,";

        assertEquals(errorMessage, d1, d2, DOUBLE_EQUALITY_TOLERANCE);
    }

    private void assertComplexNumbersEqual(ComplexNumber c1, ComplexNumber c2) {
        assertDoublesEqual(c1.getReal(), c2.getReal(), "real");
        assertDoublesEqual(c1.getImag(), c2.getImag(), "imaginary");
    }

    // Tests

    @Test
    public void testRealPartOfPurelyRealNumber() {
        double expected = 1.0;
        double actual = new ComplexNumber(1.0, 0).getReal();
        assertDoublesEqual(expected, actual, "real");
    }

    @Ignore("Remove to run test")
    @Test
    public void testRealPartOfPurelyImaginaryNumber() {
        double expected = 0.0;
        double actual = new ComplexNumber(0, 1.0).getReal();
        assertDoublesEqual(expected, actual, "real");
    }

    @Ignore("Remove to run test")
    @Test
    public void testRealPartOfNumberWithRealAndImaginaryParts() {
        double expected = 1.0;
        double actual = new ComplexNumber(1.0, 2.0).getReal();
        assertDoublesEqual(expected, actual, "real");
    }

    @Ignore("Remove to run test")
    @Test
    public void testImaginaryPartOfPurelyRealNumber() {
        double expected = 0.0;
        double actual = new ComplexNumber(1.0, 0).getImag();
        assertDoublesEqual(expected, actual, "imaginary");
    }

    @Ignore("Remove to run test")
    @Test
    public void testImaginaryPartOfPurelyImaginaryNumber() {
        double expected = 1.0;
        double actual = new ComplexNumber(0, 1.0).getImag();
        assertDoublesEqual(expected, actual, "imaginary");
    }

    @Ignore("Remove to run test")
    @Test
    public void testImaginaryPartOfNumberWithRealAndImaginaryParts() {
        double expected = 2.0;
        double actual = new ComplexNumber(1.0, 2.0).getImag();
        assertDoublesEqual(expected, actual, "imaginary");
    }

    @Ignore("Remove to run test")
    @Test
    public void testImaginaryUnitExhibitsDefiningProperty() {
        ComplexNumber expected = new ComplexNumber(-1.0, 0);
        ComplexNumber actual = new ComplexNumber(0, 1.0).times(new ComplexNumber(0, 1.0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testAdditionWithPurelyRealNumbers() {
        ComplexNumber expected = new ComplexNumber(3.0, 0);
        ComplexNumber actual = new ComplexNumber(1.0, 0).add(new ComplexNumber(2.0, 0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testAdditionWithPurelyImaginaryNumbers() {
        ComplexNumber expected = new ComplexNumber(0, 3.0);
        ComplexNumber actual = new ComplexNumber(0, 1.0).add(new ComplexNumber(0, 2.0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testAdditionWithRealAndImaginaryParts() {
        ComplexNumber expected = new ComplexNumber(4.0, 6.0);
        ComplexNumber actual = new ComplexNumber(1.0, 2.0).add(new ComplexNumber(3.0, 4.0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testSubtractionWithPurelyRealNumbers() {
        ComplexNumber expected = new ComplexNumber(-1.0, 0.0);
        ComplexNumber actual = new ComplexNumber(1.0, 0.0).minus(new ComplexNumber(2.0, 0.0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testSubtractionWithPurelyImaginaryNumbers() {
        ComplexNumber expected = new ComplexNumber(0, -1.0);
        ComplexNumber actual = new ComplexNumber(0, 1.0).minus(new ComplexNumber(0, 2.0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testSubtractionWithRealAndImaginaryParts() {
        ComplexNumber expected = new ComplexNumber(-2.0, -2.0);
        ComplexNumber actual = new ComplexNumber(1.0, 2.0).minus(new ComplexNumber(3.0, 4.0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testMultiplicationWithPurelyRealNumbers() {
        ComplexNumber expected = new ComplexNumber(2.0, 0);
        ComplexNumber actual = new ComplexNumber(1.0, 0).times(new ComplexNumber(2.0, 0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testMultiplicationWithPurelyImaginaryNumbers() {
        ComplexNumber expected = new ComplexNumber(-2.0, 0);
        ComplexNumber actual = new ComplexNumber(0, 1.0).times(new ComplexNumber(0, 2.0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testMultiplicationWithRealAndImaginaryParts() {
        ComplexNumber expected = new ComplexNumber(-5.0, 10.0);
        ComplexNumber actual = new ComplexNumber(1.0, 2.0).times(new ComplexNumber(3.0, 4.0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testDivisionWithPurelyRealNumbers() {
        ComplexNumber expected = new ComplexNumber(0.5, 0);
        ComplexNumber actual = new ComplexNumber(1.0, 0).div(new ComplexNumber(2.0, 0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testDivisionWithPurelyImaginaryNumbers() {
        ComplexNumber expected = new ComplexNumber(0.5, 0);
        ComplexNumber actual = new ComplexNumber(0, 1.0).div(new ComplexNumber(0, 2.0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testDivisionWithRealAndImaginaryParts() {
        ComplexNumber expected = new ComplexNumber(0.44, 0.08);
        ComplexNumber actual = new ComplexNumber(1.0, 2.0).div(new ComplexNumber(3.0, 4.0));
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testAbsoluteValueOfPositivePurelyRealNumber() {
        double expected = 5.0;
        double actual = new ComplexNumber(5.0, 0).abs();
        assertDoublesEqual(expected, actual, "real");
    }

    @Ignore("Remove to run test")
    @Test
    public void testAbsoluteValueOfNegativePurelyRealNumber() {
        double expected = 5.0;
        double actual = new ComplexNumber(-5.0, 0).abs();
        assertDoublesEqual(expected, actual, "real");
    }

    @Ignore("Remove to run test")
    @Test
    public void testAbsoluteValueOfPurelyImaginaryNumberWithPositiveImaginaryPart() {
        double expected = 5.0;
        double actual = new ComplexNumber(0, 5.0).abs();
        assertDoublesEqual(expected, actual, "real");
    }

    @Ignore("Remove to run test")
    @Test
    public void testAbsoluteValueOfPurelyImaginaryNumberWithNegativeImaginaryPart() {
        double expected = 5.0;
        double actual = new ComplexNumber(0, -5.0).abs();
        assertDoublesEqual(expected, actual, "real");
    }

    @Ignore("Remove to run test")
    @Test
    public void testAbsoluteValueOfNumberWithRealAndImaginaryParts() {
        double expected = 5.0;
        double actual = new ComplexNumber(3.0, 4.0).abs();
        assertDoublesEqual(expected, actual, "real");
    }

    @Ignore("Remove to run test")
    @Test
    public void testConjugationOfPurelyRealNumber() {
        ComplexNumber expected = new ComplexNumber(5.0, 0);
        ComplexNumber actual = new ComplexNumber(5.0, 0).conjugate();
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testConjugationOfPurelyImaginaryNumber() {
        ComplexNumber expected = new ComplexNumber(0, -5.0);
        ComplexNumber actual = new ComplexNumber(0, 5.0).conjugate();
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testConjugationOfNumberWithRealAndImaginaryParts() {
        ComplexNumber expected = new ComplexNumber(1.0, -1.0);
        ComplexNumber actual = new ComplexNumber(1.0, 1.0).conjugate();
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testExponentialOfPurelyImaginaryNumber() {
        ComplexNumber expected = new ComplexNumber(-1.0, 0);
        ComplexNumber actual = new ComplexNumber(0, Math.PI).exponentialOf();
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testExponentialOfZero() {
        ComplexNumber expected = new ComplexNumber(1.0, 0);
        ComplexNumber actual = new ComplexNumber(0, 0).exponentialOf();
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testExponentialOfPurelyRealNumber() {
        ComplexNumber expected = new ComplexNumber(Math.E, 0);
        ComplexNumber actual = new ComplexNumber(1.0, 0).exponentialOf();
        assertComplexNumbersEqual(expected, actual);
    }

    @Ignore("Remove to run test")
    @Test
    public void testExponentialOfNumberWithRealAndImaginaryParts() {
        ComplexNumber expected = new ComplexNumber(-2.0, 0);
        ComplexNumber actual = new ComplexNumber(Math.log(2.0), Math.PI).exponentialOf();
        assertComplexNumbersEqual(expected, actual);
    }

}
class ComplexNumber {
  private double real;
  private double imaginary;

  public ComplexNumber(double real, double imaginary) {
    this.real = real;
    this.imaginary = imaginary;
  }

  public double getReal() {
    return real;
  }

  public double getImag() {
    return imaginary;
  }

  public ComplexNumber add(ComplexNumber other) {
    return new ComplexNumber(real + other.real, imaginary + other.imaginary);
  }

  public ComplexNumber minus(ComplexNumber other) {
    return new ComplexNumber(real - other.real, imaginary - other.imaginary);
  }

  public ComplexNumber times(ComplexNumber other) {
    return new ComplexNumber(
        real * other.real - imaginary * other.imaginary,
        imaginary * other.real + real * other.imaginary);
  }

  public ComplexNumber div(ComplexNumber other) {
    double denominator = Math.pow(other.abs(), 2);
    return new ComplexNumber(
        (real * other.real + imaginary * other.imaginary) / denominator,
        (imaginary * other.real - real * other.imaginary) / denominator);
  }

  public double abs() {
    return Math.sqrt(real * real + imaginary * imaginary);
  }

  public ComplexNumber conjugate() {
    return new ComplexNumber(real, -imaginary);
  }

  public ComplexNumber exponentialOf() {
    return new ComplexNumber(
        Math.pow(Math.E, real) * Math.cos(imaginary), Math.pow(Math.E, real) * Math.sin(imaginary));
  }
}

Community comments

Find this solution interesting? Ask the author a question to learn more.

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?
  • Are there new concepts here that you could read more about to improve your understanding?