ActiveState Code

Recipe 576407: Quadratic


Quadratic can be used by students for solving quadratic equations ax^2+bx+c a!=0, which are given by the quadratic formula x = -b + SQUARE-ROOT(b^2-4ac)/2a and x = -b - SQUARE-ROOT(b^2-4ac)/2a However,if b^2-4ac is negative the solutions are not real but complex numbers of the form a+bj. Though, both real and complex solutions are called using Quadratic

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#On the name of ALLAH
#Author : Fouad Teniou
#Date : 05/08/08
#Version : 2.4

import cmath as c
import math as m

################################################################## 
# x**2 = -1 an equation which does not have a solution in the real number field
# i = Square-Root (-1)  < -- > i**2 = -1 made it possible to develop the complex numbers
# of the form a + bj
################################################################### 

class Quadratic:
	def __call__(self,**args):
	      self.args = args
	      if (len(args) == 3 and self.args.has_key('a') and self.args.get('a') !=0 
                       and self.args.has_key('b') and self.args.has_key('c')):
       	            if ((self.args.get('b'))**2-(4*(self.args.get('a'))*(self.args.get('c'))))>=0:
		         self.compute1 = "%2.2f" % float(((self.args.get('b')*(-1))+(m.sqrt((self.args.get('b'))**
					2-(4*(self.args.get('a'))*(self.args.get('c'))))))/(2*self.args.get('a')))
		         self.compute2 = "%2.2f" % float(((self.args.get('b')*(-1))-(m.sqrt((self.args.get('b'))**
					2-(4*(self.args.get('a'))*(self.args.get('c'))))))/(2*self.args.get('a')))
                    elif ((self.args.get('b'))**2-(4*(self.args.get('a'))*(self.args.get('c'))))<0:
		         self.compute1 = "%2.2f" % float(((self.args.get('b')*(-1))+(c.sqrt((self.args.get('b'))**
					2-(4*(self.args.get('a'))*(self.args.get('c'))))))/(2*self.args.get('a')))
		         self.compute2 = "%2.2f" % float(((self.args.get('b')*(-1))-(c.sqrt((self.args.get('b'))**
					2-(4*(self.args.get('a'))*(self.args.get('c'))))))/(2*self.args.get('a')))
	       else:
		   self.args = 0
                
               return (self.compute1,self.compute2)

	def __str__(self):
	      if self.args == 0:
		return '\n<Quadratic : Equation should be of the form of ax%+bx+c (a=?,b=?,c=?) and a !=0' % chr(253)
	      else:
		   if self.compute1==self.compute2:
		        return ('\n<Quadratic : Equation of the form %sx%s +(%s)x+(%s) = 0 \n\n<Solutions : x = %s\n\t'
			% (self.args.get('a'),chr(253),self.args.get('b'),self.args.get('c'),self.compute1))
		   else:     
                        return ('\n<Quadratic : Equation of the form %sx%s +(%s)x+(%s) = 0 \n\n<Solutions : x = %s\n\t       x = %s'
			% (self.args.get('a'),chr(253),self.args.get('b'),self.args.get('c'),self.compute1,self.compute2))

if __name__ =='__main__':
	y = Quadratic()
	y(a=7,b=-2,c=-2)
	print y
	y(a=-1,b=4,c=-5)
	print y
	y(a=4,b=-4,c=1)
	print y
	y(a=0,b=3,c=3)
	print y

Comments

  1. 1. At 1:47 p.m. on 5 aug 2008, david decotigny said:

    I don't understand why there are so many "args.get('X')". And this OOP-style __str__ is not consistent with the non-OOP-style __call__. Here is another version:

    import math, cmath
    
    def polynome2str(*factors): # Greatest power to smallest
        def lmonome(factor, degree):
            if not factor:
                return ()
            if factor > 0:
                sign = "+"
            else:
                sign = "-"
                factor = -factor            
            if degree == 0:
                x = ""
            elif degree == 1:
                x = "x"
            else:
                x = "x^%d" % degree
            if degree > 0 and factor in (-1, 1): factor = ""
            return (sign, "%s%s" % (factor, x))
    
        result = []
        for f, d in zip(factors, range(len(factors)-1, -1, -1)):
            result += list(lmonome(f, d))
        if len(result) > 1 and result[0] == "+": result = result[1:]
        return " ".join(result)
    
    
    class Quadratic:
        a, b, c   = None, None, None
        degree    = None
        solutions = None
    
        def __init__(self, **args):
            self.a = a = args.get("a", 0)
            self.b = b = args.get("b", 0)
            self.c = c = args.get("c", 0)
            self.degree = 2
            delta = b**2 - 4.*a*c
            if a == 0:
                assert b != 0, "Not an equation: %s = 0" % c
                # Linear equation
                self.degree = 1
                self.solutions = (-c / b,)
            elif delta == 0:
                self.solutions = (-b / (2.*a),)
            elif delta > 0:
                s = math.sqrt(delta)
                self.solutions = ( (-b - s) / (2.*a), (-b + s) / (2.*a) )
            else: # delta < 0 => complex solution
                s = cmath.sqrt(delta)
                self.solutions = ( (-b - s) / (2.*a), (-b + s) / (2.*a) )
    
        def __str__(self):
            a, b, c = (self.a, self.b, self.c)
            if self.degree == 1:
                return "Linear equation %s = 0, solution is: %s" \
                       % (polynome2str(b, c), self.solutions[0])
            s = polynome2str(a, b, c)
            if len(self.solutions) == 1:
                return "Quadratic equation %s = %s.(%s)^2 = 0, unique solution is: %s"\
                       % (s, a, polynome2str(1, b/(2.*a)), self.solutions[0])
            else:
                t = (s,) + self.solutions
                return "Quadratic equation %s = 0, solutions are: %s and %s" % t
    
    
    if __name__ =='__main__':
            y = Quadratic(a=7,b=-2,c=-2)
            print y
            y = Quadratic(a=-1,b=4,c=-5)
            print y
            y = Quadratic(a=4,b=-4,c=1)
            print y
            y = Quadratic(a=0,b=3,c=3)
            print y
    
  2. 2. At 12:01 a.m. on 6 aug 2008, Gary Eakins said:

    What does "#On the name of ALLAH" have to do with Python?

  3. 3. At 3:33 a.m. on 6 aug 2008, Fouad Teniou (the author) said:

    Thank you for your comment David Decotiny However, the args.get('a'),('b'),('c')are calling the dictionary values by keys once the user input them to perform the quadratic operations solutions -b(+ -)square-root(b^2 - 4ac)/2a. and if you look at my Pycol program where I used the OOP style you can see that I used the __repr__ for printing but not in this program because it works better. However, you can use both, it will depend of the order you want the execution of your program and the outcome The __call__ is made for calling the class directly instead of defining it by other name say( eg if I defined it as equation : if __name__=='__main__' y=Quadratic() y.equation(a=?,b=?,c=?) print y I hope that you will see the difference and will realise why I called it directly.

  4. 4. At 3:41 a.m. on 6 aug 2008, Fouad Teniou (the author) said:

    I use on the name of ALLAH because I am a Muslim and that is the way we write or say before we start doing things such as ( studying or eating ) for God bounty and I hope you will do one day yourself and see the difference of performing any task in your life, thus, On the name of ALLAH does have nothing to do with python and as you can realise that is not part of the code.

  5. 5. At 5:25 p.m. on 7 aug 2008, Jack Trainor said:

    Fixed a bug and normalized output to complex numbers.

    import math
    import cmath
    
    def solve_quadratic_equation(a, b, c):
        roots = []
        try:
            if a != 0:
                discriminant = b**2 - 4*a*c
                neg_b_div_2a = -(b/(2*a))
                if discriminant > 0:
                    sqrt_discriminant_div_2a = math.sqrt(discriminant)/2*a
                    roots.append(complex(neg_b_div_2a + sqrt_discriminant_div_2a, 0))
                    roots.append(complex(neg_b_div_2a - sqrt_discriminant_div_2a, 0))
                elif discriminant == 0:
                    roots.append(complex(neg_b_div_2a, 0))
                else:
                    sqrt_discriminant_div_2a = cmath.sqrt(-discriminant)/2*a
                    roots.append(complex(neg_b_div_2a, sqrt_discriminant_div_2a))
                    roots.append(complex(neg_b_div_2a, -sqrt_discriminant_div_2a))
            else:
                raise Exception, "a == 0"
        except Exception, e:
            print("%s: %s" % ("solve_quadratic_equation failed", e))
        return roots
    
    if __name__ =='__main__':
        print solve_quadratic_equation(1, 0, -64)
        print solve_quadratic_equation(1, 0, 64)
        print solve_quadratic_equation(1, 4, 4)
        print solve_quadratic_equation(0, 0, 64)
    
  6. 6. At 5:35 p.m. on 7 aug 2008, Jack Trainor said:

    Hmm...not sure why the comment editor switched my comments and timestamps around. #5 should be my second post.

  7. 7. At 6:43 p.m. on 7 aug 2008, Jack Trainor said:

    This recipe is entirely unreadable and current version fails at line 20. (And it's revision 12.)

    The intention here is to solve an equation. I don't see the need to get fancy and create a class, make it a callable object and override __str__. Plus the values of a, b, c should be extracted once to variables as David D. recommended.

    If one wants to check the input or format the output, I suggest those be done separately. Here's my version which makes the math pretty clear.

    import math
    import cmath
    
    def solve_quadratic_equation(a, b, c):
        roots = []
        try:
            if a != 0:
                discriminant = b**2 - 4*a*c
                neg_b_div_2a = -(b/(2*a))
                if discriminant > 0:
                    sqrt_discriminant_div_2a = math.sqrt(discriminant)/2*a
                    roots.append(neg_b_div_2a + sqrt_discriminant_div_2a)
                    roots.append(neg_b_div_2a - sqrt_discriminant_div_2a)
                elif discriminant == 0:
                    roots.append(neg_b_div_2a)
                else:
                    sqrt_discriminant_div_2a = cmath.sqrt(-discriminant)/2*a
                    roots.append(complex(neg_b_div_2a, sqrt_discriminant_div_2a))
                    roots.append(complex(neg_b_div_2a, sqrt_discriminant_div_2a))
            else:
                print("%s: %s" % ("solve_quadratic_equation failed", "a == 0"))
        except Exception, e:
            print("%s: %s" % ("solve_quadratic_equation failed", e))
        return roots
    
    if __name__ =='__main__':
        print solve_quadratic_equation(1, 0, -64)
        print solve_quadratic_equation(1, 0, 64)
    
  8. 8. At 5:39 a.m. on 8 aug 2008, Fouad Teniou (the author) said:

    You should know that I am using a Central Library for posting my programs and therefore I tried to use Word document, cut and pace from my original version, which I wrote and which is working perfectly and providing professional outcome, and which I tested on DOS before I posted it. However, I noticed there is a bracket missing on line 20 and 25 and I expect people as your self to be able to correct such anomalies since they are out of control sometimes while the Word cut and pace process is not working especially here at the Central Library which I do have to use for personal reasons. I used the Class method, because this is the way I do write my programs, ( Fancy ways) and people do have different style even in what they eat or the way they do it. Though people will import the class or use it as part of other programs, because this is the Mathematics branch, and people use for different purpose ( Finance ,Statistics, Accounting etc,etc………………………………. Quadratic is a superb program and is working perfectly and other students and Tutors will find it extremely useful whether to check or to rely on for their professional work. I realised that you used exceptions on your version and again this is up to people to choose their style, and I do not see the need of raising exceptions because Python raise exceptions automatically with their own wordings. I use the if statement which I believe is more professional and the is the best style, since it is based on logic which is a branch in Mathematics and which is the branch I did study and gain an International Baccalaureate in 1987

  9. 9. At 1:04 a.m. on 5 oct 2008, David Lambert said:

    If 4 a c is much less than b squared then the formula, for roots while mathematically correct is numerically poor. See this link for better logic:

    http://thornahawk.unitedti.org/

  10. 10. At 4:33 a.m. on 8 nov 2008, Fouad Teniou (the author) said:

    You should have read the comment on the top of the program ( if b^2-4ac is negative the solutions are not real but complex numbers of the form a+bj. Though, both real and complex solutions are called using Quadratic) we get the complex number solution. However, as you should be aware of the use of complex numbers in the mathematic field. And I even noticed in the web link you mentioned that there is a reference to people want to use the complex solutions which could be for higher levels in mathematics field

Sign in to comment