""" Approximates the area under the curve using the trapezoidal rule """ from typing import Callable, Union def trapezoidal_area( fnc: Callable[[Union[int, float]], Union[int, float]], x_start: Union[int, float], x_end: Union[int, float], steps: int = 100, ) -> float: """ Treats curve as a collection of linear lines and sums the area of the trapezium shape they form :param fnc: a function which defines a curve :param x_start: left end point to indicate the start of line segment :param x_end: right end point to indicate end of line segment :param steps: an accuracy gauge; more steps increases the accuracy :return: a float representing the length of the curve >>> def f(x): ... return 5 >>> f"{trapezoidal_area(f, 12.0, 14.0, 1000):.3f}" '10.000' >>> def f(x): ... return 9*x**2 >>> f"{trapezoidal_area(f, -4.0, 0, 10000):.4f}" '192.0000' >>> f"{trapezoidal_area(f, -4.0, 4.0, 10000):.4f}" '384.0000' """ x1 = x_start fx1 = fnc(x_start) area = 0.0 for i in range(steps): # Approximates small segments of curve as linear and solve # for trapezoidal area x2 = (x_end - x_start) / steps + x1 fx2 = fnc(x2) area += abs(fx2 + fx1) * (x2 - x1) / 2 # Increment step x1 = x2 fx1 = fx2 return area if __name__ == "__main__": def f(x): return x ** 3 + x ** 2 print("f(x) = x^3 + x^2") print("The area between the curve, x = -5, x = 5 and the x axis is:") i = 10 while i <= 100000: print(f"with {i} steps: {trapezoidal_area(f, -5, 5, i)}") i *= 10