|
| 1 | +""" |
| 2 | +Approximates the area under the curve using the trapezoidal rule |
| 3 | +""" |
| 4 | + |
| 5 | +from typing import Callable, Union |
| 6 | + |
| 7 | +def trapezoidal_area(fnc: Callable[[Union[int, float]], Union[int, float]], |
| 8 | + x_start: Union[int, float], |
| 9 | + x_end: Union[int, float], |
| 10 | + steps: int = 100) -> float: |
| 11 | + """ |
| 12 | + Treats curve as a collection of linear lines and sums the area of the |
| 13 | + trapezium shape they form |
| 14 | + :param fnc: a function which defines a curve |
| 15 | + :param x_start: left end point to indicate the start of line segment |
| 16 | + :param x_end: right end point to indicate end of line segment |
| 17 | + :param steps: an accuracy gauge; more steps increases the accuracy |
| 18 | + :return: a float representing the length of the curve |
| 19 | +
|
| 20 | + >>> def f(x): |
| 21 | + ... return 5 |
| 22 | + >>> f"{trapezoidal_area(f, 12.0, 14.0, 1000):.3f}" |
| 23 | + '10.000' |
| 24 | + >>> def f(x): |
| 25 | + ... return 9*x**2 |
| 26 | + >>> f"{trapezoidal_area(f, -4.0, 0, 10000):.4f}" |
| 27 | + '192.0000' |
| 28 | + >>> f"{trapezoidal_area(f, -4.0, 4.0, 10000):.4f}" |
| 29 | + '384.0000' |
| 30 | + """ |
| 31 | + x1 = x_start |
| 32 | + fx1 = fnc(x_start) |
| 33 | + area = 0.0 |
| 34 | + for i in range(steps): |
| 35 | + # Approximates small segments of curve as linear and solve |
| 36 | + # for trapezoidal area |
| 37 | + x2 = (x_end - x_start)/steps + x1 |
| 38 | + fx2 = fnc(x2) |
| 39 | + area += abs(fx2 + fx1) * (x2 - x1)/2 |
| 40 | + # Increment step |
| 41 | + x1 = x2 |
| 42 | + fx1 = fx2 |
| 43 | + return area |
| 44 | + |
| 45 | + |
| 46 | +if __name__ == "__main__": |
| 47 | + def f(x): |
| 48 | + return x**3 + x**2 |
| 49 | + |
| 50 | + print("f(x) = x^3 + x^2") |
| 51 | + print("The area between the curve, x = -5, x = 5 and the x axis is:") |
| 52 | + i = 10 |
| 53 | + while i <= 100000: |
| 54 | + print(f"with {i} steps: {trapezoidal_area(f, -5, 5, i)}") |
| 55 | + i*=10 |
0 commit comments