EECS2030 Lab 3 Feedback 1.4 / 2 -passes all unit and style tests? -------------------- TA Comments: -in equals, you have to check if this.getClass() == obj.getClass() before casting obj to a Complex reference -there is no need to append ".0" to the end of the real and imaginary parts in toString -what happens if c.imaginary == 0 in toString? -you should not use == to compare strings; strings are reference types and you (almost) always use equals to compare reference types for equality -------------------- Style checker output: YOUR SUBMISSION FAILED SOME BASIC STYLE CHECKS Here is the style checker output: Starting audit... /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:15:40: '(' is preceded with whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:15:45: ',' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:16:46: ',' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:61:39: ',' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:74:40: ',' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:109:44: ',' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:141:40: ',' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:220:19: 'if' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:220:31: '>' is not preceded with whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:220:32: '>' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:223:24: 'if' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:223:36: '<' is not preceded with whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:223:37: '<' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:253:19: 'if' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:254:27: 'if' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:255:35: 'if' is not followed by whitespace. /home/burton/work/teaching/2017F/2030/marking/lab3/aneeb/src/eecs2030/lab3/Complex.java:255:72: Must have at least one statement. Audit done. -------------------- 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..E.E..... Time: 0.032 There were 3 failures: 1) test08_equals(eecs2030.lab3.ComplexTest) java.lang.ClassCastException: eecs2030.lab3.ComplexTest$Pair cannot be cast to eecs2030.lab3.Complex 2) test10_toString(eecs2030.lab3.ComplexTest) org.junit.ComparisonFailure: toString returned the wrong string expected:<0.0[ + ]0.0i> but was:<0.0[.00.]0.0i> 3) test11_valueOf(eecs2030.lab3.ComplexTest) java.lang.IllegalArgumentException: Numbers aren't separated by a + or - sign! FAILURES!!! Tests run: 18, Failures: 3 -------------------- 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 { private final double real; private final double imaginary; static Complex I = new Complex (0.0,1.0); static Complex ONE = new Complex(1.0,0.0); /** * Initializes this complex number to <code>0 + 0i</code>. * */ public Complex() { this.real = 0.0; this.imaginary = 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.real = other.real; this.imaginary = other.imaginary; } /** * 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.imaginary = 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) { return new Complex(re,0.0); } /** * 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) { return new Complex(0.0,im); } /** * 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.imaginary; } /** * 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) { Complex d = this; double newReal = c.real + d.real; double newImaginary = c.imaginary + d.imaginary; return new Complex(newReal,newImaginary); } /** * 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) { Complex d = this; double newReal = c.real * d.real - c.imaginary * d.imaginary; double newImaginary = c.real * d.imaginary + c.imaginary * d.real; return new Complex(newReal, newImaginary); } /** * Compute the magnitude of this complex number. * * @return the magnitude of this complex number. */ public double mag() { return Math.hypot(real,imaginary); } /** * 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() { Complex c = this; double hashReal = 9999 * c.real; double hashImaginary = 99 * c.imaginary; double sum = hashReal + hashImaginary; 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) { Complex c = this; Complex d = (Complex) obj; if (obj == null) return false; if (obj.getClass() != c.getClass()) return false; return (c.real == d.real) && (c.imaginary == d.imaginary); } /** * 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() { Complex c = this; String sign = ""; if(c.imaginary>0) { sign = " + "; } else if(c.imaginary<0) { sign = " - "; } return c.real + ".0" + sign + Math.abs(imaginary) + ".0" + "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+")); double real = 0; if(parts.size() == 3) { if(parts.get(2) == "+" || parts.get(2) == "-") { if(parts.get(3).endsWith("i") == true) { } else { throw new IllegalArgumentException("Imaginary number doesnt end with i!"); } } else { throw new IllegalArgumentException("Numbers aren't separated by a + or - sign!"); } } else { throw new IllegalArgumentException("Invalid Entry"); } // 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 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); for (int t = 0; t < max; t++) { if (z.mag() > 2.0) return t; z = z.multiply(z).add(c); } // 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. return max; } }