-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathpolynomial.py
138 lines (116 loc) · 4.34 KB
/
polynomial.py
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""
Implement a data type named Polynomial such that
-- it is easy to specify the polynomial to be constructed,
for example it should be easy to create x^100 - 2.5 x^2 + 3
-- it provides a string representation of a polynomial that is similar to the way
the polynomial is normally written. For example, 3 x^4 - 2.3 x^2 + 0.1 x + 7
-- a method is provided to compute the derivative of a polynomial
-- client code can write/compute the sum of two polynomials p and q
with the expression p+q
In addition,
-- given a plynomial p, the expression p(v) evaluates p at v. For example, p(3)
evaulates p at 3 and returns this value
"""
from numbers import Number
def nomial(coeff, exponent):
"""
A helper function:
Given coeff and exponent, this function produces
a text resentatioln of the nomial.
For example, nomial(2,3) returns the string "2 x**3"
"""
if coeff == 0: # Zen of Python: flat is better than nested
return "0"
if exponent == 0:
return str(coeff)
if exponent == 1:
if coeff == 1:
return "x"
else:
return "%s x" % coeff
else:
if coeff == 1:
return "x**%s" % exponent
else:
return "%s x**%s" % (coeff, exponent)
class polynomial:
def __init__(self, *args):
d = self.coeff = {}
exponents = self.exponent = set() # intrinstically, the set of exponents is part of the representation
# of a polynomial
if args: # if non-empty
for coeff, exponent in args: # Zen of Python: flat is better than nested
if not isinstance(coeff, Number):
raise RuntimeError("Coefficient must be numbers!")
if (type(exponent) != int) or (exponent < 0):
raise RuntimeError("Exponent must be non-negative integer!")
if coeff == 0: continue
if exponent not in exponents:
exponents.add(exponent)
d[exponent] = coeff
else:
d[exponent] += coeff
self.get_rid_of_zero_coeffs()
def get_rid_of_zero_coeffs(self):
d = self.coeff
exponents = self.exponent
non_zero_terms = [exponent for exponent in d if d[exponent] != 0]
set_of_non_zero_terms = set(non_zero_terms)
if set_of_non_zero_terms < exponents:
zero_terms = exponents - set_of_non_zero_terms
for exponent in zero_terms:
del d[exponent]
self.exponent = set_of_non_zero_terms
if not self.exponent:
self.exponent = set([0])
self.coeff = {0:0}
put_in_canonical_form = get_rid_of_zero_coeffs # useful alise
def __str__(self):
exponents = self.exponent
coeff = self.coeff
terms_list = list(exponents)
terms_list.sort()
terms_list.reverse()
terms = [nomial(coeff[exponent], exponent) for exponent in terms_list]
poly = " + ".join(terms)
poly = poly.replace("+ -", "- ")
return poly
def derivative(self):
exponent = self.exponent
coeff = self.coeff
if 0 in exponent:
exponent = exponent - {0}
new_coeff = {}
for exp in exponent:
new_coeff[exp - 1] = exp * coeff[exp]
p = polynomial()
p.exponent = set([n - 1 for n in exponent])
p.coeff = new_coeff
p.put_in_canonical_form()
return p
def __add__(self, other):
exp1 = self.exponent
exp2 = other.exponent
coeff1 = self.coeff
coeff2 = other.coeff
coeff = {}
for exp in (exp1 - exp2):
coeff[exp] = coeff1[exp]
for exp in (exp2 - exp1):
coeff[exp] = coeff2[exp]
for exp in (exp1 & exp2):
coeff[exp] = coeff1[exp] + coeff2[exp]
p = polynomial()
p.exponent = exp1 | exp2
p.coeff = coeff
p.get_rid_of_zero_coeffs()
return p
def __call__(self, x):
coeff = self.coeff
total = 0
for exponent in coeff:
total += coeff[exponent] * x ** exponent
return total
if __name__ == '__main__':
p = polynomial()
q = polynomial((1,2), (-3,2), (100.34, 100)) # etc