Skip to content

Commit e25d424

Browse files
shrabianpoyea
authored andcommitted
Added an algorithm that approximates line lengths (TheAlgorithms#1692)
* A recursive insertion sort * added doctests and typehints * Added arc length and numerical integration calculators * fixed doc test * Fixed some conversion errors * Fixed some commenting * Deleted numerical integration to allow 1 file per push * Changed string formatting method
1 parent 99ebd1a commit e25d424

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

maths/line_length.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from typing import Callable, Union
2+
import math as m
3+
4+
def line_length(fnc: Callable[[Union[int, float]], Union[int, float]],
5+
x_start: Union[int, float],
6+
x_end: Union[int, float],
7+
steps: int = 100) -> float:
8+
9+
"""
10+
Approximates the arc length of a line segment by treating the curve as a
11+
sequence of linear lines and summing their lengths
12+
:param fnc: a function which defines a curve
13+
:param x_start: left end point to indicate the start of line segment
14+
:param x_end: right end point to indicate end of line segment
15+
:param steps: an accuracy gauge; more steps increases accuracy
16+
:return: a float representing the length of the curve
17+
18+
>>> def f(x):
19+
... return x
20+
>>> f"{line_length(f, 0, 1, 10):.6f}"
21+
'1.414214'
22+
23+
>>> def f(x):
24+
... return 1
25+
>>> f"{line_length(f, -5.5, 4.5):.6f}"
26+
'10.000000'
27+
28+
>>> def f(x):
29+
... return m.sin(5 * x) + m.cos(10 * x) + x * x/10
30+
>>> f"{line_length(f, 0.0, 10.0, 10000):.6f}"
31+
'69.534930'
32+
"""
33+
34+
x1 = x_start
35+
fx1 = fnc(x_start)
36+
length = 0.0
37+
38+
for i in range(steps):
39+
40+
# Approximates curve as a sequence of linear lines and sums their length
41+
x2 = (x_end - x_start) / steps + x1
42+
fx2 = fnc(x2)
43+
length += m.hypot(x2 - x1, fx2 - fx1)
44+
45+
# Increment step
46+
x1 = x2
47+
fx1 = fx2
48+
49+
return length
50+
51+
if __name__ == "__main__":
52+
53+
def f(x):
54+
return m.sin(10*x)
55+
56+
print("f(x) = sin(10 * x)")
57+
print("The length of the curve from x = -10 to x = 10 is:")
58+
i = 10
59+
while i <= 100000:
60+
print(f"With {i} steps: {line_length(f, -10, 10, i)}")
61+
i *= 10

maths/numerical_integration.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
"""
13+
Treats curve as a collection of linear lines and sums the area of the
14+
trapezium shape they form
15+
:param fnc: a function which defines a curve
16+
:param x_start: left end point to indicate the start of line segment
17+
:param x_end: right end point to indicate end of line segment
18+
:param steps: an accuracy gauge; more steps increases the accuracy
19+
:return: a float representing the length of the curve
20+
21+
>>> def f(x):
22+
... return 5
23+
>>> '%.3f' % trapezoidal_area(f, 12.0, 14.0, 1000)
24+
'10.000'
25+
26+
>>> def f(x):
27+
... return 9*x**2
28+
>>> '%.4f' % trapezoidal_area(f, -4.0, 0, 10000)
29+
'192.0000'
30+
31+
>>> '%.4f' % trapezoidal_area(f, -4.0, 4.0, 10000)
32+
'384.0000'
33+
"""
34+
x1 = x_start
35+
fx1 = fnc(x_start)
36+
area = 0.0
37+
38+
for i in range(steps):
39+
40+
# Approximates small segments of curve as linear and solve
41+
# for trapezoidal area
42+
x2 = (x_end - x_start)/steps + x1
43+
fx2 = fnc(x2)
44+
area += abs(fx2 + fx1) * (x2 - x1)/2
45+
46+
# Increment step
47+
x1 = x2
48+
fx1 = fx2
49+
return area
50+
51+
52+
if __name__ == "__main__":
53+
54+
def f(x):
55+
return x**3
56+
57+
print("f(x) = x^3")
58+
print("The area between the curve, x = -10, x = 10 and the x axis is:")
59+
i = 10
60+
while i <= 100000:
61+
area = trapezoidal_area(f, -5, 5, i)
62+
print("with {} steps: {}".format(i, area))
63+
i*=10

0 commit comments

Comments
 (0)