Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions polynomial/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,24 @@ def nth_derivative(self, n=1):
in zip(self, reversed(factors))]
)

def integral(self, a, b):
"""Return the integral of self from a to b."""
res = self.indefinite_integral
# Last term of indefinite integral is C.
res[0] = 0
return res.calculate(b) - res.calculate(a)

@property
def indefinite_integral(self):
"""Return the polynomial object which is the integral of self."""
if not self:
return Polynomial("C")

return Polynomial(
[c/x for c, x in
zip(self, range(self.degree + 1, 0, -1))] + ["C"]
)

Comment on lines +146 to +163
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest adding a parameter for the value of the integration constant, since having the string "C" prevents the polynomial from being very useful for almost all operations and is maybe a not-so-desired result, as opposed to a plain 0 for example. Maybe having the parameter like constant="C" would cover that case, also there would be no need of lines 149 and 150 then.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would you cover the case of double integrals? Would we make constants a seperate polynomial that goes at the end?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, currently we haven't implemented anything allowing operations between string and number coefficients, which would be needed for applying indefinite_integral to a polynomial ending with "C". So three options come in my head in this scenario:

  1. throwing an error (current)
    or
  2. implementing something like nth_integral which returns two things: the result without the constants and a polynomial with the constants
    or
  3. implementing a class Integral which handles this and can have a polynomial be easily extracted from it

@property
def terms(self):
"""Get the terms of self as a list of tuples in coeff, deg form.
Expand Down
34 changes: 34 additions & 0 deletions tests/test_polynomials_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,40 @@ def test_nth_derivative(self):
result = p.nth_derivative(10)
self._assert_polynomials_are_the_same(pd, result)

def test_integral_zero(self):
"""Test that the integral of the zero polynomial is 'C'."""
p = Polynomial()
z = ZeroPolynomial()
e = Polynomial("C")

self._assert_polynomials_are_the_same(e, z.indefinite_integral)
self._assert_polynomials_are_the_same(e, p.indefinite_integral)

def test_integral_constant(self):
"""Test that integrating against a constant is correct."""
p = Polynomial()
z = ZeroPolynomial()

self.assertEqual(0, z.integral(-1000, 1000))
self.assertEqual(0, p.integral(-1000, 1000))

c = Constant(2)
p = Polynomial(3)
m = Monomial(1.2, 0)

self.assertEqual(20, c.integral(-5, 5))
self.assertEqual(45, p.integral(-10, 5))
self.assertAlmostEqual(48, m.integral(-50.5, -10.5))

def test_general_integral(self):
"""Test that integration works as expected."""
p = Polynomial(3, 2, 1)
expected = Polynomial(1.0, 1.0, 1.0, "C")
result = p.indefinite_integral
self._assert_polynomials_are_the_same(expected, result)
self.assertAlmostEqual(3, p.integral(0, 1))
self.assertAlmostEqual(4, p.integral(-1, 1))


if __name__ == '__main__':
unittest.main()