EECS2030 Lab 3 Feedback
1.8 / 2 -passes all unit and style tests?
--------------------
TA Comments:
-in valueOf, you should not use != to compare strings; strings are
reference value types, and you always use equals to compare
reference value types for equality
--------------------
Style checker output:
--------------------
Unit tester output:
YOUR SUMBISSION FAILED SOME UNIT TESTS
Here is the test output:
java -classpath .:/home/burton/work/teaching/2017F/2030/marking/lab3/_jar/* org.junit.runner.JUnitCore eecs2030.lab3.Lab3Suite
JUnit version 4.12
.............E.....
Time: 0.035
There was 1 failure:
1) test11_valueOf(eecs2030.lab3.ComplexTest)
java.lang.IllegalArgumentException: Not a complex number
FAILURES!!!
Tests run: 18, Failures: 1
--------------------
Your submission:
Complex.java
package eecs2030.lab3;
import java.util.Arrays;
import java.util.List;
/**
* A class that represents immutable complex numbers.
*
* @author EECS2030 Fall 2017-18
*
*/
public final class Complex {
public static final Complex ONE = new Complex(1, 0);
public static final Complex I = new Complex(0, 1);
private final double real;
private final double imag;
/**
* Initializes this complex number to <code>0 + 0i</code>.
*
*/
public Complex() {
this(0.0, 0.0);
}
/**
* Initializes this complex number so that it has the same real and
* imaginary parts as another complex number.
*
* @param other
* the complex number to copy.
*/
public Complex(Complex other) {
this(other.real, other.imag);
}
/**
* Initializes this complex number so that it has the given real and
* imaginary components.
*
* @param re
* the real part of the complex number.
* @param im
* the imaginary part of the complex number.
*/
public Complex(double re, double im) {
this.real = re;
this.imag = im;
}
/**
* A static factory method that returns a new complex number whose real part
* is equal to re and whose imaginary part is equal to 0.0
*
* @param re
* the desired real part of the complex number
* @return a new complex number whose real part is equal to re and whose
* imaginary part is equal to 0.0
*/
public static Complex real(double re) {
double real = re;
double imag = 0.0;
return new Complex(real, imag);
}
/**
* A static factory method that returns a new complex number whose real part
* is equal to 0.0 and whose imaginary part is equal to im
*
* @param im
* the desired imaginary part of the complex number
* @return a new complex number whose real part is equal to 0.0 and whose
* imaginary part is equal to im
*/
public static Complex imag(double im) {
double real = 0.0;
double imag = im;
return new Complex(real, imag);
}
/**
* Get the real part of the complex number.
*
* @return the real part of the complex number.
*/
public double re() {
return this.real;
}
/**
* Get the imaginary part of the complex number.
*
* @return the imaginary part of the complex number.
*/
public double im() {
return this.imag;
}
/**
* Add this complex number and another complex number to obtain a new
* complex number. Neither this complex number nor c is changed by this
* method.
*
* @param c
* The complex number to add to this complex number.
* @return a new Complex number equal to the sum of this complex number and
* c.
*/
public Complex add(Complex c) {
double a = this.real + c.real;
double b = this.imag + c.imag;
return new Complex(a, b);
}
/**
* Multiply this complex number with another complex number to obtain a new
* complex number. Neither this complex number nor c is changed by this
* method.
*
* <p>
* This is not an industrial strength implementation of complex number
* multiplication. In particular, issues related to the differences between
* <code>-0.0</code> and <code>0.0</code> and infinite real or imaginary
* parts are not taken into account.
*
* @param c
* The complex number to multiply by.
* @return a new Complex number equal to this complex number multiplied by
* c.
*/
public Complex multiply(Complex c) {
double a = (this.real * c.real) - (this.imag * c.imag);
double b = (this.imag * c.real) + (this.real * c.imag);
return new Complex(a, b);
}
/**
* Compute the magnitude of this complex number.
*
* @return the magnitude of this complex number.
*/
public double mag() {
return Math.hypot(this.real, this.imag);
}
/**
* Return a hash code for this complex number.
*
* <p>
* This implementation uses a very crude algorithm to compute the hash code;
* the hash code is computed as follows:
*
* <ol>
* <li>compute the value equal to <code>9999</code> times the real part of
* this complex number
* <li>compute the value equal to <code>99</code> times the imaginary part
* of this complex number
* <li>compute the sum of the values computed in Steps 1 and 2
* <li>casts the value computed in Step 3 to an <code>int</code>
* <li>returns the value computed in Step 4
* </ol>
*
* <p>
* In production code, consider implementing hashCode() using
* {@link java.util.Objects#hash}
*
* @return a hash code value for this complex number.
*/
@Override
public int hashCode() {
double valueReal = 9999 * this.real;
double valueImag = 99 * this.imag;
double sum = valueReal + valueImag;
return (int) sum;
}
/**
* Compares this complex number with the specified object. The result is
* <code>true</code> if and only if the argument is a <code>Complex</code>
* number with the same real and imaginary parts as this complex number.
*
* @param obj
* the object to compare this Complex number against.
* @return true if the given object is a Complex number equal to this
* complex number, false otherwise.
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Complex other = (Complex) obj;
return (this.real == other.real) && (this.imag == other.imag);
}
/**
* Returns a string representation of this complex number.
*
* <p>
* The returned string is the real part of the complex number, followed by a
* space, followed by a <code>+</code> or <code>-</code> sign, followed by a
* space, followed by the absolute value of the imaginary part of the
* complex number, followed by an <code>i</code>. The sign is <code>+</code>
* if the imaginary part of the complex number is positive, and
* <code>-</code> if the imaginary part of the complex number is negative.
*
* For example the complex number with real and imaginary parts equal to
* zero has the string representation <code>0.0 + 0.0i</code>. The complex
* number with real part equal to zero and imaginary part equal to
* <code>-1</code> has the string representation <code>0.0 - 1.0i</code>.
*
* @return a string representation of this complex number.
*
*/
@Override
public String toString() {
String sign;
if (this.imag >= 0) {
sign = "+";
} else {
sign = "-";
}
return this.real + " " + sign + " " + Math.abs(this.imag) + "i";
}
/**
* Returns a complex number holding the value represented by the given
* string.
*
* <p>
* <code>valueOf</code> tries to create a complex number from a string
* representation of the complex number. Strings that can interpreted as
* complex numbers are those strings returned by
* <code>Complex.toString</code>.
*
* @param s
* a string representation of a complex number.
* @return a Complex number equal to the complex number represented by the
* given string.
* @throws IllegalArgumentException
* if the string cannot be interpreted as a complex
* number. @pre. s has a space before and after the + or - sign
* separating the real and imaginary parts of the complex number
*/
public static Complex valueOf(String s) {
Complex result = null;
String t = s.trim();
List<String> parts = Arrays.asList(t.split("\\s+"));
// split splits the string s by looking for spaces in s.
// If s is a string that might be interpreted as a complex number
// then parts will be a list having 3 elements. The first
// element will be a real number, the second element will be
// a plus or minus sign, and the third element will be a real
// number followed immediately by an i.
//
// To complete the implementation of this method you need
// to do the following:
//
// -check if parts has 3 elements
// -check if the second element of parts is "+" or "-"
// -check if the third element of parts ends with an "i"
// -if any of the 3 checks are false then s isn't a complex number
// and you should throw an exception
// -if all of the 3 checks are true then s might a complex number
// -try to convert the first element of parts to a double value
// (use Double.valueOf); this might fail in which case s isn't
// a complex number
// -remove the 'i' from the third element of parts and try
// to convert the resulting string to a double value
// (use Double.valueOf); this might fail in which case s isn't
// a complex number
// -you now have real and imaginary parts of the complex number
// but you still have to account for the "+" or "-" which
// is stored as the second element of parts
// -once you account for the sign, you can return the correct
// complex number
if (parts.size() != 3) {
throw new IllegalArgumentException("Not a complex number");
}
if (parts.get(1) != "+" || parts.get(1) != "-") {
throw new IllegalArgumentException("Not a complex number");
}
if (parts.get(2).endsWith("i") == false) {
throw new IllegalArgumentException("Not a complex number");
}
double real = Double.valueOf(parts.get(0));
double imagAbs = Double.valueOf(parts.get(2).replace("i", ""));
double imag;
if (parts.get(1) == "-") {
imag = imagAbs * -1;
} else {
imag = imagAbs;
}
result = new Complex(real, imag);
return result;
}
}
MandelbrotUtil.java
package eecs2030.lab3;
public class MandelbrotUtil {
private MandelbrotUtil() {
}
/**
* Return the number of iterations needed to determine if z(n + 1) = z(n) *
* z(n) + c remains bounded where z(0) = 0 + 0i. z(n + 1) is bounded if its
* magnitude is less than or equal to 2. Returns 1 if the magnitude of c is
* greater than 2. Returns max if the magnitude of z(n + 1) is less than or
* equal to 2 after max iterations.
*
* <p>
* If z(n + 1) remains bounded after max iterations then c is assumed to be
* in the Mandelbrot set.
*
* @param c
* a complex number
* @param max
* the maximum number of iterations to attempt
* @return the number of iterations needed to determine if z(n + 1) = z(n) *
* z(n) + c remains bounded where z(0) = 0.0 + 0.0i. @pre. max is
* greater than 0
*/
public static int mandelbrotIterations(Complex c, int max) {
Complex z = new Complex(0.0, 0.0);
Complex zn = new Complex(0.0, 1.0);
// You need a loop here. Inside the loop, set z to z * z + c
// (i.e. perform one iteration of the equation) and
// check if the magnitude of z is greater than 2; if
// the magnitude is greater than 2 then return the
// number of times you computed z * z + c.
// If you compute z * z + c max times and the magnitude
// of z is still less than or equal to 2 you should
// return max.
if (c.mag() > 2) {
return 1;
}
for (int i = 0; i < max; i++) {
zn = z.multiply(z).add(c);
double zMag = z.mag();
if (zMag > 2) {
return i;
}
z = zn;
}
return max;
}
}