CS 171 & 171L Introduction to Computer Science I & Lab Fall 2020

## Lab 7: Quadratics

In this lab, you will create a class that allows one to use quadratic functions. You should start off with s1 driving and s2 navigating.

### 1. Introductions

Introduce yourself to your lab partner. Tell your lab partner about your plans for Spring Break.

In this lab you will familiarize yourself with the java representation of objects by working with a class which supports quadratic functions.

A quadratic function in its simplest form is represented by $f(x) = ax^2 + bx + c,$ where $$a$$, $$b$$, and $$c$$ are real numbers (in general they can be complex). The graph of $$f$$ is a parabola with axis of symmetry at $$x = -b/(2 a)$$, vertex at $$(-b/(2 a), f(-b/(2 a)))$$. It opens up if $$a > 0$$, down if $$a < 0$$, and is a line if $$a = 0$$. The term $$D = b^2 - 4ac$$ is called the discriminant and tells us about the roots based on the following three cases:

1. If $$D>0$$, then there are two unequal purely real roots and the parabola crosses the $$x$$-axis. $r_1 = \underbrace{\dfrac{-b}{2a} + \dfrac{\sqrt{D}}{2a}}_{\text{re part}} + \underbrace{0}_{\text{im part}}i \quad\text{and}\quad r_2 = \underbrace{\dfrac{-b}{2a} - \dfrac{\sqrt{D}}{2a}}_{\text{re part}} + \underbrace{0}_{\text{im part}}i$
2. If $$D=0$$, then there is one repeated real root because the vertex is on the $$x$$-axis. $r_1 = r_2 = -b/(2 a) = \underbrace{-b/(2 a)}_{\text{re part}} + \underbrace{0}_{\text{im part}}i.$
3. If $$D<0$$, then there are two unequal complex roots that are conjugate pairs, and the parabola does not cross or touch the $$x$$-axis. $r_1 = \underbrace{\dfrac{-b}{2a}}_{\text{re part}} + \underbrace{\dfrac{\sqrt{-D}}{2a}}_{\text{im part}}i \quad\text{and}\quad r_2 = \underbrace{\dfrac{-b}{2a}}_{\text{re part}} + \underbrace{\dfrac{-\sqrt{-D}}{2a}}_{\text{im part}}i$

## Coding

Copy from the file the Lab7.pde into a new Processing window and save this as Lab7. Create a new tab and call it Point2D then copy the code from the Point2D.pde (see below) to that window. Create a new tab and call it Line then copy the code from the Line.pde (see below) to that window. Create a new tab and call it Quadratic then copy the code from the Quadratic.pde (see below) to that window. Create a new tab and call it Complex then copy the code from the Complex.pde (see below), or code from your lab, to that window. Complete the methods in Quadratic.pde, as shown below.

  // Globals to allow persistence // setting bounds on our "world" coordinates float xmin = -10; float xmax = 10; float ymin = -10; float ymax = 10; // screen bound coordinates float umin = 0; float umax = 900; float vmin = 900; float vmax = 0; Point2D p1, p2; Line L1, L2, L3, L4, L5; Quadratic q1, q2; void setup() { size(900, 900); reset(); testing(); noLoop(); // no animation } void testing() { System.out.println("- - - - - - - - - - - - - - - - -"); q1 = new Quadratic(1, -5, 6); System.out.println(q1); // 1.0 x^2 + -5.0 x + 6.0 System.out.println(q1.concaveUp()); // true System.out.println(q1.concaveDown()); // false System.out.println(q1.f(0)); // 6 System.out.println(q1.f(3)); // 0 System.out.println(q1.f(2)); // 0 p1 = q1.vertex(); System.out.println(p1); // (2.5, -0.25) System.out.println(q1.f(q1.vertex().x)); // -0.25 System.out.println(q1.slope(4)); // 3 System.out.println(q1.integrate(0,2)); // 4.66666666 System.out.println(q1.discriminant()); // 1.0 System.out.println(q1.realRootCount()); // 2 System.out.println(q1.root1()); // 3.0 System.out.println(q1.root2()); // 2.0 L1 = q1.derivative(1); System.out.println(L1); // y = -3.0 x + 5.0 System.out.println("- - - - - - - - - - - - - - - - -"); q2 = new Quadratic(-1,-2,-3); System.out.println(q2); // -1.0 x^2 + -2.0 x + -3.0 System.out.println(q2.concaveUp()); // false System.out.println(q2.concaveDown()); // true System.out.println(q2.f(0)); // -3 System.out.println(q2.f(3)); // -18 System.out.println(q2.f(2)); // -11 p2 = q2.vertex(); System.out.println(p2); // (2.5, -0.25) System.out.println(q2.vertex()); // (-1,-2) System.out.println(q2.f(q2.vertex().x)); // -2 System.out.println(q2.slope(4)); // -10 System.out.println(q2.integrate(0,2)); // -12.66666666 System.out.println(q2.discriminant()); // -8 System.out.println(q2.root1()); // -1.0+1.4142135623730951i System.out.println(q2.root2()); // -1.0-1.4142135623730951i System.out.println(q1.realRootCount()); // 2 L2 = q2.derivative(1); System.out.println(L2); // y = -4.0 x + -2.0 } void draw() { background(224); axes(); // draw x and y axes strokeWeight(0.5); stroke(128); grid(1, 1); // draw grid strokeWeight(1); stroke(0); grid(5, 5); // draw grid drawLabels(5, 5); //stroke(0, 0, 255); //plot(L1); //plot(L2); //stroke(0, 255, 255); //plot(L3); //fill(255,0,0); stroke(255,0,0); plot(q1); stroke(0, 255, 0); plot(q2); } void plot(Point2D p) { if (p == null) return; // no point to plot strokeWeight(6); float u = map(p.x, xmin, xmax, umin, umax); float v = map(p.y, ymin, ymax, vmin, vmax); ellipse(u, v, 6, 6); } void plot(Line L) { if (L == null) return; strokeWeight(4); float x = xmin; float dx = (xmax-xmin)/width; float u1 = 0; float v1 = 0; float u2 = 0; float v2 = 0; boolean first = true; while (x <= xmax) { float y = L.f(x); // x to u u2 = map(x, xmin, xmax, umin, umax); // y to v v2 = map(y, ymin, ymax, vmin, vmax); point(u1, v1); if (!first) { line(u1, v1, u2, v2); } else { first = false; } x += dx; // saving for next iteration u1 = u2; v1 = v2; } } void plot(Quadratic Q) { if (Q == null) return; float x = xmin; float dx = (xmax-xmin)/width; float u1 = 0; float v1 = 0; float u2 = 0; float v2 = 0; boolean first = true; while (x <= xmax) { float y = (float) Q.f(x); u2 = map(x, xmin, xmax, umin, umax); v2 = map(y, ymin, ymax, vmin, vmax); point(u1, v1); if (!first) { line(u1, v1, u2, v2); } else { first = false; } x += dx; // saving for next iteration u1 = u2; v1 = v2; } // show roots if (Q.realRootCount() == 2) { plot(new Point2D((float)(Q.root1().re), 0)); plot(new Point2D((float)(Q.root2().re), 0)); } else if (Q.realRootCount() == 1) { plot(new Point2D((float)(Q.root1().re), 0)); } // show vertex plot(Q.vertex()); } void axes() { strokeWeight(2); stroke(0); // x-axis is a horizontal line at y = 0 and from xmin to xmax // need: line(xmin, y, xmax, y) // map from world coordinates onto screen coordinates float v = map(0, ymin, ymax, vmin, vmax); line(umin, v, umax, v); // y-axis is a verical line at x = 0 and from ymin to ymax // need: line(ymin, x, ymax, x) float u = map(0, xmin, xmax, umin, umax); line(u, vmin, u, vmax); } // draw a grid with dx and dy spacing void grid(float dx, float dy) { // vertical lines float x = 0; while (x <= xmax) { float u = map(x, xmin, xmax, umin, umax); // map x to u line(u, vmin, u, vmax); // draw vertical line x += dx; //increment x } x = 0; while (x >= xmin) { float u = map(x, xmin, xmax, umin, umax); // map x to u line(u, vmin, u, vmax); // draw vertical line x -= dx; //decrement x } // horizontal lines for (float y = 0; y <= ymax; y += dy) { float v = map(y, ymin, ymax, vmin, vmax); // map y to v line(umin, v, umax, v); // draw horizontal line } for (float y = 0; y >= ymin; y -= dy) { float v = map(y, ymin, ymax, vmin, vmax); // map y to v line(umin, v, umax, v); // draw horizontal line } } void drawLabels(float dx, float dy) { textSize(16); fill(0); float u = map(0, xmin, xmax, umin, umax); float v = map(0, ymin, ymax, vmin, vmax); text("0", u, v); for (float x = dx; x <= xmax; x+= dx) { u = map(x, xmin, xmax, umin, umax); // need better formatting text(String.format("%.0f",x), u, v); } for (float x = -dx; x >= xmin; x-= dx) { u = map(x, xmin, xmax, umin, umax); // need better formatting text(String.format("%.0f",x), u, v); } u = map(0, xmin, xmax, umin, umax); for (float y = dy; y <= ymax; y+= dy) { v = map(y, ymin, ymax, vmin, vmax); // need better formatting text(String.format("%.0f",y), u, v); } for (float y = -dy; y >= ymin; y-= dy) { v = map(y, ymin, ymax, vmin, vmax); // need better formatting text(String.format("%.0f",y), u, v); } } // zoom by a factor of 2 on the point clicked by the user // reduce (xmax-xmin) and (ymax-ymix) by a factor of 2 void mouseClicked() { // (mouseX, mouseY) is in screen (u,v) coordinates // map that to world (x,y) coordinates float x = map(mouseX, umin, umax, xmin, xmax); float y = map(mouseY, vmin, vmax, ymin, ymax); float dx1 = xmax-xmin; // computing the x range float dy1 = ymax-ymin; // comuting the y range float dx2 = dx1/2; // reduce the x range by a factor of 2 float dy2 = dy1/2; // reduce the y range by a factor of 2 xmin = x - dx2/2; xmax = x + dx2/2; ymin = y - dy2/2; ymax = y + dy2/2; redraw(); } void reset() { xmin = -20; ymin = -20; xmax = 20; ymax = 20; } void keyPressed() { if (key=='r') { reset(); redraw(); // a processing defined function } if (key == 's') { save("plot.jpg"); } } 

  // a class to represent a point on the plane public static class Point2D { // this is a speacial keyword that refers to this instance // similar to "my name" OR "my address" float x, y; // this.x, this.y // a constructor for the point (x$, y$) public Point2D(float x, float y) { this.x = x; this.y = y; } // a default constructor to construct the point (0,0) public Point2D() { x = 0; y = 0; } // a copy constructor to construct the point identical to p public Point2D(Point2D p) { x = p.x; y = p.y; } // an equals method --- x coordinates are equal and the y coordinates are equal public boolean equals(Point2D p) { //if (x == p.x && y == p.y) return true; //else return false; return x == p.x && y == p.y; } // distance from this point to the origin float distance() { return sqrt(x*x+y*y); } // distance from this point to the point p float distance(Point2D p) { float dx = x-p.x; // this point's x - p's x float dy = y-p.y; // this point's y - p's y return sqrt(dx*dx+dy*dy); } // a toString method is called implicitly when a printable version is needed public String toString() { return "(" + x + "," + y + ")"; } } 

  public static class Line { // the line y=mx+b in the plane // f(x) = mx+b float m; // slope float b; // intercept // send in a slope and intercept public Line(float m$, float b$) { m = m$; b = b$; } // copy constructor public Line(Line L) { m = L.m; b = L.b; } // send in a slope and point public Line(float m$, Point2D p) { m = m$; b = p.y - m*p.x; } // send in a two points public Line(Point2D p1, Point2D p2) { // (p1.y-p2.y)/(p1.x-p2.x) == dy/dx this((p1.y-p2.y)/(p1.x-p2.x), p1); // invoke the slope-point constructor } public String toString() { return "y = " + m + "x + " + b; } public float f(float x) { float y = m*x + b; return y; // return m*x+b; // more compact } // compute the intersection point where this Line intersections L public Point2D intersection(Line L) { if (m==L.m) return null; // lines are parallel and no intersection point exists float x = (L.b-b)/(m-L.m); float y = f(x); return new Point2D(x,y); } public float getSlope() { return m; } public float getYIntercept() { return b; } public float getXIntercept() { return -b/m; } } 

  public static class Quadratic { // three double instance variables representing a, b, and c. double a, b, c; // Constructor that takes three double parameters representing a, b, and c. public Quadratic(double a$, double b$, double c\$) { } // Constructor that copies a Quadratic public Quadratic(Quadratic q) { } // printable form of this quadratic public String toString() { return "0 x^2 + 0 x + 0"; } // returns a double representing quadratic function evaluated at x. public double f(double x) { return 0.0; } // returns the discriminant of this quadratic: (b^2 - 4 a c) public double discriminant() { return 0.0; } // returns a boolean that is true if the graph of the quadratic opens up public boolean concaveUp() { return false; } // returns a boolean that is true if the graph of the quadratic opens down public boolean concaveDown() { return false; } // returns an int that represents the number of real roots of this quadratic // 0 - both roots are complex when the discriminant is negative // 1 - both roots are equal and real when the discriminant is zero // 2 - both roots are real an distinct when the discriminant is positive public int realRootCount() { return 0; } // returns a Complex value that represents the first root of the polynomial // Hint: Use the discriminant and realRootCount functions public Complex root1() { return new Complex(0.0D, 0.0D); } // returns a Complex value that represents the first root of the polynomial // Hint: Use the discriminant and realRootCount functions public Complex root2() { return new Complex(0.0D, 0.0D); } // returns a Point2D representing the vetex of the parabola // Recall that the vertex of the parablola is given by (-b/(2a), f(-b/(2a))) public Point2D vertex() { return new Point2D(0.0, 0.0); } // returns a double that is the insantaneous slope of this Quadratic at x: 2 a x + b public double slope(double x) { return 0.0; } // returns a line that represents the derivative of this Quadratic at x // 2 a x + b is the slope // (x, f(x)) is a point on the line // Use point-slope equation to determine the y intercept public Line derivative(double x) { return new Line(0.0, 0.0); } // integral-ish helper method // Define F(x) = (a/3)x^3 + (b/2)x^2 + c x double F(double x) { return 0.0; } // returns a double representing the definite integral from x1 < x2 of this quadratic. // intgrate(x1,x2) returns F(x2) - F(x1). public double integrate(double x1, double x2) { return 0.0; } } 

  // Represents a complex number using two doubles, // one for the real component and // one for the imaginary component public static class Complex { double re, im; // Create printable format // a+bi if b != 0 OR // a if b==0 public String toString() { if (im == 0) return String.format("%f", re); if (re == 0) return String.format("%fi", im); if (im < 0) return String.format("%f-%fi", re, -im); return String.format("%f+%fi", re, im); } // General constructor creates a+bi public Complex(double a, double b) { re = a; im = b; } } 

When you are finished, email your lab files to your lab partner and instructor.