import java.util.Random; /** This sets a quadratic equation question. The solutions may be real or complex, and partial credit is given for the case where some but not all of the answers are correct. @author Melvin Fitting @version April, 2003 @version Revised December, 2007 */ public class Quadratic implements Question { private int a, b, c; // Think of these integers as determining the equation // ax^2 + bx + c = 0 private boolean real; // true if solutions real, else false private boolean sreal; // sreal is student's answer to whether the solutions are real private double ans1Real, ans1Imaginary, ans2Real, ans2Imaginary; // real and imaginary parts of the two answers. If the solutions // are real, the variables for the imaginary parts are not used. private double sans1Real, sans1Imaginary, sans2Real, sans2Imaginary; // The student's answers for real and imaginary parts of the // two solutions /** The constructor devises a quadratic equation in which the coefficients are integers in "reasonable" ranges. */ public Quadratic(Random r) { a = r.nextInt(2) + 1; b = r.nextInt(7) - 3; c = r.nextInt(7) -3; double disc = b*b - 4*a*c; real = (disc >= 0); if (real) { ans1Real = (-b + Math.sqrt(disc))/(2*a); ans2Real = (-b - Math.sqrt(disc))/(2*a); } else { ans1Real = ans2Real = -((double)b)/(2*a); ans1Imaginary = Math.sqrt(-disc)/(2*a); ans2Imaginary = -ans1Imaginary; } } /** Returns the question as an array of size 3. The entries are a,b,c, where the problem is to solve ax^2 + bx + c = 0. */ public Object[] getQuestion() { Object[] question = {new Integer(a), new Integer(b), new Integer(c)}; return question; } /** Takes an array of size either 2 or 4, containing Object. If solutions are real, array is size 2 and components 0 and 1 contain the answers. If solutions are complex, size is 4 and components 0 and 1 contain answer 1, real and imaginary parts, and components 2 and 3 hold answer 2. */ public void putAnswer(Object[] answer) { if (answer.length == 2) { sreal = true; sans1Real = (Double)answer[0]; sans2Real = (Double)answer[1]; } else { sreal = false; sans1Real = (Double)answer[0]; sans1Imaginary = (Double)answer[1]; sans2Real = (Double)answer[2]; sans2Imaginary = (Double)answer[3]; } } /** Returns the correct answer as an array of Double. If answers are real, array is of size 2, and entries are the two answers. If answers are complex, array is of size 4, and entries are real and imaginary part of first answer, and real and imaginary part of second answer. */ public Object[] getAnswer() { Object[] realOnly = {new Double(ans1Real), new Double(ans2Real)}; Object[] realComplex = {new Double(ans1Real), new Double(ans2Imaginary), new Double(ans2Real), new Double(ans2Imaginary)}; if (real) return realOnly; else return realComplex; } public int getScore() { int score = 0; if (real != sreal) return score; score = 2; if (real) { if (eq(ans1Real, sans1Real) || eq(ans2Real, sans2Real)) { score += 4; if (eq(ans1Real, sans1Real) && eq(ans2Real, sans2Real)) score += 4; } else if (eq(ans1Real, sans2Real) || eq(ans2Real, sans1Real)) { score += 4; if (eq(ans1Real, sans2Real) && eq(ans2Real, sans1Real)) score += 4; } } else //if complex { if (eq(ans1Real, ans1Imaginary, sans1Real, sans1Imaginary) || eq(ans2Real, ans2Imaginary, sans2Real, sans2Imaginary)) { score += 4; if (eq(ans1Real, ans1Imaginary, sans1Real, sans1Imaginary) && eq(ans2Real, ans2Imaginary, sans2Real, sans2Imaginary)) score += 4; } else if (eq(ans1Real, ans1Imaginary, sans2Real, sans2Imaginary) || eq(ans2Real, ans2Imaginary, sans1Real, sans1Imaginary)) { score += 4; if (eq(ans1Real, ans1Imaginary, sans2Real, sans2Imaginary) && eq(ans2Real, ans2Imaginary, sans1Real, sans1Imaginary)) score += 4; } } return score; } //checking reals for "close enough" private boolean eq(double ans, double sans) { return Math.abs(ans - sans) < ACC_ERR; } //checking complex for "close enough" private boolean eq(double ansReal, double ansIm, double sansReal, double sansIm) { return eq(ansReal, sansReal) && eq(ansIm, sansIm); } }