Albion College

CS 171

Introduction to Computer Science I & Lab

Fall 2025

Lab 10: Classes and Objects

Goals and Objectives

The main goal this lab is for you to get a more practice with Pythons's object oriented programming constructs.

Introductions

Introduce yourself to your lab partner(s). What classes are you planning on taking next semester?

Download the lab

Download the source file Lab10.py. It contains the stubs of Python functions. Open it in the IDLE Python environment.

Background

In this lab you will familiarize yourself with the python 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\]

Seek help as soon as you are experiencing difficulty with this assignment.
Do not wait until the deadline to seek help!

Coding

Complete the methods in Lab10.py.

Quadratic.java

# Lab 10 - Classes for points, lines, and quadratics # YOUR NAMES HERE import math # a few items about complex numbers def warmup(): z = 1j # sqrt(-1) print("z = sqrt(-1) = i = 1j = ", z) print("z's type is ", type(z)) print("z*z = -1 = ", z*z) re = (z*z).real # real part im = (z*z).imag # imaginary part print("re im = ", re, im) # i^i = e^{-pi/2} print("i^i = e^{-pi/2} = ", z**z) print("i^i = e^{-pi/2} = ", math.exp(-math.pi/2)) # roots of f(x) = x*x - 5*x + 7 # a = 1, b = -5, c = 7 r1 = (5/2) - (math.sqrt(3)/2)*1j r2 = (5/2) + (math.sqrt(3)/2)*1j print(r1, r2) print(r1*r1 - 5*r1 + 7) # 0j = 0 + 0j print(r2*r2 - 5*r2 + 7) # 0j = 0 + 0j # construct a complex number from two real parts # 3 + 2j re = 3 im = 2 z1 = re + im*1j print("z1 = ", z1) z2 = complex(re, im) print("z2 = ", z2) # a purely real number, represented as a complex number re = 10 im = 0 z3 = complex(re, im) print("z3 = 10 = 10 + 0j = ", z3) print() return # a class to represent a 2D Point class Point: def __init__(self, x, y): # constructor self.x = x self.y = y def __str__(self): # printable string version return "(" + str(self.x) + "," + str(self.y) + ")" # distance from this point (self) to the point p def distance(self, p): dx = p.x-self.x dy = p.y-self.y return math.sqrt(dx*dx + dy*dy) # a class to represent a line --- y = m x + b class Line: def __init__(self, v1, v2): # constructor - three variants # slope-intercept form if isinstance(v1, (float, int)) and isinstance(v2, (float, int)): self.m = v1 self.b = v2 # point-slope form elif isinstance(v1, Point) and isinstance(v2, (float, int)): p1 = v1 m = v2 b = p1.y - m*p1.x self.m = m self.b = b # point-point form elif isinstance(v1, Point) and isinstance(v2, Point): p1 = v1 p2 = v2 m = (p2.y - p1.y)/(p2.x - p1.x) b = p1.y - m*p1.x self.m = m self.b = b def __str__(self): # printable string version return "y = " + str(self.m) + " x + " + str(self.b) # evaluate f(x) = mx + b def f(self, x): return self.m*x + self.b # return slope def slope(self): return self.m # return intercept def intercept(self): return self.b # where does the line cross the x-axis: f(x) = 0 def xintercept(self): return -self.b/self.m # return True is self and L are parallel lines def isParallel(self, L): return math.isclose(self.m,L.m) def isPerpendicular(self, L): return math.isclose(self.m*L.m, -1) # return the unique point of intersection or None def intersection(self, L): if (self.isParallel(L)): return None x = (L.intercept() - self.b)/(self.m - L.slope()) y = self.f(x) return Point(x,y) # return a Line parallel through a given point def parallel(self, p): return Line(p, self.m) # return a Line perpendicular through a given point def perpendicular(self, p): return Line(p, -1/self.m) # Class to represent a quadratic function --- a x^2 + b x + c # where x^Y represents x raised to the y power class Quadratic: # WORKS AS IS! def __init__(self, a, b, c): # constructor # coefficients self.a = a self.b = b self.c = c # WORKS AS IS! def __str__(self): # printable string version return "y = " + \ str(self.a) + " x^2 + " + \ str(self.b) + " x + " + \ str(self.c) # returns a double representing quadratic function evaluated at x # a x^2 + b x + c # works even if x is complex! def f(self, x): return 0 # returns the discriminant of this quadratic: (b^2 - 4 a c) def discriminant(self): return 0 # returns True if the graph of the quadratic opens up \/ def isConcaveUp(self): return False # returns True if the graph of the quadratic opens down /\ def isConcaveDown(self): return False # returns an int that represents the number of distinct 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 and distinct when the discriminant is positive def realRootCount(self): return -1 # returns a complex value that represents the first root # use quadratic formula - https://en.wikipedia.org/wiki/Quadratic_formula # see https://www.tutorialspoint.com/complex-numbers-in-python # note that if D is negative, then -D is positive # use math.sqrt(v) and not v**0.5 for computing square roots def root1(self): re = 0 im = 0 return complex(re,im) # returns a complex value that represents the second root # might be the same as root1 # use math.sqrt(v) and not v**0.5 for computing square roots def root2(self): return complex(0,0) # returns a Point representing the vetex of the parabola # Recall that the vertex of the parabola is given by (-b/(2a), f(-b/(2a))) def vertex(self): return Point(0,0) # returns the instantaneous slope of this Quadratic at x: 2 a x + b def slope(self, x): return 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 Line constructor def derivative(self, x): return Line(0,0) # integral-ish helper method # Define F(x) = (a/3)x^3 + (b/2)x^2 + c x def F(self, x): return 0 # returns a double representing the definite integral from x1 < x2 # integrate(x1,x2) returns F(x2) - F(x1) def integrate(self, x1, x2): return 0 def main(): # refresher on complex numbers warmup() # Test code for Point class print("Point Testing") p1 = Point(0,0) p2 = Point(6,8) print(p1, p2) print(p1.distance(p2), Point.distance(p1,p2)) # 10.0 10.0 --- two equivalent ways to accomplish same things # Comment out as needed # Test code for Line class print("\nLine Testing") line1 = Line(2, 3) # point-slope contruction print(line1) # y = 2 x + 3 line2 = Line(Point(1,5), -1/2) # point-slope contruction print(line2) # y = -0.5 x + 5.5 line3 = Line(Point(2,2), Point(3,4)) print(line3) # y = 2.0 x + -2.0 print(Line.isParallel(line1, line2)) # False print(line1.isParallel(line3)) # True print(line2.isParallel(line3)) # False print(Line.isPerpendicular(line1, line2)) # True print(line1.isPerpendicular(line3)) # False print(line2.isPerpendicular(line3)) # True print(Line.intersection(line1, line2)) # (1.0,5.0) print(line1.intersection(line3)) # None print(line2.intersection(line3)) # (3.0,4.0) # Comment out as needed # Test code for Quadratic class print("\nQuadratic Testing") print("q1") q1 = Quadratic(1.0, -5.0, 6.0) print(q1) # 1.0 x^2 + -5.0 x + 6.0 print(q1.isConcaveUp()) # True print(q1.isConcaveDown()) # False print(q1.f(0)) # 6.0 print(q1.f(2)) # 0.0 print(q1.f(3)) # 0.0 print("vertex is", q1.vertex()) # (2.5, -0.25) print("axis of symmetry is", q1.f(q1.vertex().x)) # -0.25 print("slope at x=4 is", q1.slope(4)) # 3 print(q1.integrate(0,2)) # 4.66666666 print(q1.discriminant()) # 1.0 print(q1.realRootCount()) # 2 print(q1.root1()) # 3.0 print(q1.root2()) # 2.0 print(q1.f(q1.root1())) # (0+0j) print(q1.f(q1.root2())) # (0+0j) print(q1.derivative(1)) # y = 2.0 x - 5.0 print("- - - - - - - - - - - - - - - - -") print("q2") q2 = Quadratic(-1.0,-2.0,-3.0) print(q2) # -1.0 x^2 + -2.0 x - 3.0 print(q2.isConcaveUp()) # False print(q2.isConcaveDown()) # True print(q2.f(0)) # -3 print(q2.f(2)) # -11 print(q2.f(3)) # -18 print("vertex is", q2.vertex()) # (-1,-2) print("axis of symmetry is", q2.f(q2.vertex().x)) # -2 print("slope at x=4 is", q2.slope(4)) # -10 print(q2.integrate(0,2)) # -12.66666666 print(q2.discriminant()) # -8 print(q2.root1()) # (-1.0-1.4142135623730951j) print(q2.root2()) # (-1.0+1.4142135623730951j) print(q2.f(q2.root1())) # (0+0j) print(q2.f(q2.root2())) # (0+0j) print(q2.realRootCount()) # 0 print(q2.derivative(1)) # y = -2.0 x + -2.0 print("- - - - - - - - - - - - - - - - -") print("q3") q3 = Quadratic(0.2,2,5) print(q3) # 0.2 x^2 + 2.0 x + 5.0 print(q3.isConcaveUp()) # True print(q3.isConcaveDown()) # Falso print(q3.f(0)) # 5 print(q3.f(-5)) # 0 print(q3.f(-15)) # 20 print(q3.vertex()) # (-5,0) print(q3.f(q3.vertex().x)) # 0 print("slope at x=0 is", q3.slope(0)) # 2 print(q3.integrate(-5,10)) # 225 print(q3.discriminant()) # 0 print(q3.root1()) # -5.0 print(q3.root2()) # -5.0 print(q3.f(q3.root1())) # (0+0j) print(q3.f(q3.root2())) # (0+0j) print(q3.realRootCount()) # 1 print(q3.derivative(0)) # y = 0.4 x + 2.0 main()

Final Steps

When done, email you lab partner and instructor your lab (.py file).