From 9db2ab1b5e74df6d1d4dc086ad077f66759670d5 Mon Sep 17 00:00:00 2001 From: "arvid@12test.be" Date: Sat, 17 Oct 2026 10:05:15 +0200 Subject: [PATCH 1/7] Added algorithm: - lateral_surface_area_hemisphere(): calculate lateral surface area of a hemisphere - lateral_surface_area_conical_frustum(): calculate lateral surface area of conical frustrum - area_triangle_side_angle_side(): calculate area when 2 sides and angle are given - area_triangle_angle_side_angle(): calculate area when 2 angles and side are given Fixes: - Changed instances of "1/2 * formula" into "formula / 2" as it is more accurate in edga case of floating point precision Documentation changes: - fixed a few typos, - added formulas, add wikipedia references --- maths/area.py | 232 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 206 insertions(+), 26 deletions(-) diff --git a/maths/area.py b/maths/area.py index 5ed3457a8c8f..c8e154bdfcdf 100644 --- a/maths/area.py +++ b/maths/area.py @@ -1,14 +1,16 @@ """ -Find the area of various geometric shapes +Calculate the area of various geometric 2D and 3D shapes Wikipedia reference: https://en.wikipedia.org/wiki/Area """ -from math import pi, sqrt, tan +from math import pi, radians, sin, sqrt, tan def surface_area_cube(side_length: float) -> float: """ - Calculate the Surface Area of a Cube. + Calculate the surface area of a cube. + Wikipedia reference: https://en.wikipedia.org/wiki/Cube + Formula: 6 * side_length^2 >>> surface_area_cube(1) 6 @@ -30,7 +32,9 @@ def surface_area_cube(side_length: float) -> float: def surface_area_cuboid(length: float, breadth: float, height: float) -> float: """ - Calculate the Surface Area of a Cuboid. + Calculate the surface area of a rectangular cuboid. + Wikipedia reference: https://en.wikipedia.org/wiki/Cuboid + Formula: 2 * (l*b + b*h + h*l) >>> surface_area_cuboid(1, 2, 3) 22 @@ -58,7 +62,7 @@ def surface_area_cuboid(length: float, breadth: float, height: float) -> float: def surface_area_sphere(radius: float) -> float: """ - Calculate the Surface Area of a Sphere. + Calculate the surface area of a sphere. Wikipedia reference: https://en.wikipedia.org/wiki/Sphere Formula: 4 * pi * r^2 @@ -82,7 +86,8 @@ def surface_area_sphere(radius: float) -> float: def surface_area_hemisphere(radius: float) -> float: """ - Calculate the Surface Area of a Hemisphere. + Calculate the surface area of a hemisphere. + Wikipedia reference: https://en.wikipedia.org/wiki/Sphere Formula: 3 * pi * r^2 >>> surface_area_hemisphere(5) @@ -103,9 +108,33 @@ def surface_area_hemisphere(radius: float) -> float: return 3 * pi * radius**2 +def lateral_surface_area_hemisphere(radius: float) -> float: + """ + Calculate the lateral surface area of a hemisphere. + Wikipedia reference: https://en.wikipedia.org/wiki/Sphere + Formula: 2 * pi * r^2 + + >>> lateral_surface_area_hemisphere(5) + 157.07963267948966 + >>> lateral_surface_area_hemisphere(1) + 6.283185307179586 + >>> lateral_surface_area_hemisphere(0) + 0.0 + >>> lateral_surface_area_hemisphere(1.1) + 7.602654221687301 + >>> lateral_surface_area_hemisphere(-1) + Traceback (most recent call last): + ... + ValueError: surface_area_hemisphere() only accepts non-negative values + """ + if radius < 0: + raise ValueError("surface_area_hemisphere() only accepts non-negative values") + return 2 * pi * radius**2 + + def surface_area_cone(radius: float, height: float) -> float: """ - Calculate the Surface Area of a Cone. + Calculate the surface area of a cone. Wikipedia reference: https://en.wikipedia.org/wiki/Cone Formula: pi * r * (r + (h ** 2 + r ** 2) ** 0.5) @@ -137,7 +166,7 @@ def surface_area_cone(radius: float, height: float) -> float: def lateral_surface_cone(radius: float, height: float) -> float: """ - Calculate the Lateral Surface Area of a Cone. + Calculate the lateral surface area of a cone. Wikipedia reference: https://en.wikipedia.org/wiki/Cone Formula: pi * r * (h ** 2 + r ** 2) ** 0.5 @@ -165,7 +194,9 @@ def surface_area_conical_frustum( radius_1: float, radius_2: float, height: float ) -> float: """ - Calculate the Surface Area of a Conical Frustum. + Calculate the surface area of a conical frustum. + Wikipedia reference: https://en.wikipedia.org/wiki/Frustum#Surface_area + Formula: pi * (r1 + r2) * (r1 - r2)^2 + pi * (r1^2 + r2^2) >>> surface_area_conical_frustum(1, 2, 3) 45.511728065337266 @@ -196,9 +227,46 @@ def surface_area_conical_frustum( return pi * ((slant_height * (radius_1 + radius_2)) + radius_1**2 + radius_2**2) +def lateral_surface_area_conical_frustum( + radius_1: float, radius_2: float, height: float +) -> float: + """ + Calculate the lateral surface area of a conical frustum. + Wikipedia reference: https://en.wikipedia.org/wiki/Frustum#Surface_area + Formula: pi * (radius_1 + radius_2) * (radius_1 - radius_2)^2 + + >>> lateral_surface_area_conical_frustum(1, 2, 3) + 29.803764797388304 + >>> lateral_surface_area_conical_frustum(4, 5, 6) + 171.98605870844534 + >>> lateral_surface_area_conical_frustum(0, 0, 0) + 0.0 + >>> lateral_surface_area_conical_frustum(1.6, 2.6, 3.6) + 49.2994270760586 + >>> lateral_surface_area_conical_frustum(-1, 2, 3) + Traceback (most recent call last): + ... + ValueError: surface_area_conical_frustum() only accepts non-negative values + >>> lateral_surface_area_conical_frustum(1, -2, 3) + Traceback (most recent call last): + ... + ValueError: surface_area_conical_frustum() only accepts non-negative values + >>> lateral_surface_area_conical_frustum(1, 2, -3) + Traceback (most recent call last): + ... + ValueError: surface_area_conical_frustum() only accepts non-negative values + """ + if radius_1 < 0 or radius_2 < 0 or height < 0: + raise ValueError( + "surface_area_conical_frustum() only accepts non-negative values" + ) + slant_height = (height**2 + (radius_1 - radius_2) ** 2) ** 0.5 + return pi * slant_height * (radius_1 + radius_2) + + def surface_area_cylinder(radius: float, height: float) -> float: """ - Calculate the Surface Area of a Cylinder. + Calculate the surface area of a cylinder. Wikipedia reference: https://en.wikipedia.org/wiki/Cylinder Formula: 2 * pi * r * (h + r) @@ -230,7 +298,7 @@ def surface_area_cylinder(radius: float, height: float) -> float: def lateral_surface_cylinder(radius: float, height: float) -> float: """ - Calculate the Lateral Surface Area of a Cylinder. + Calculate the lateral surface area of a cylinder. Wikipedia reference: https://en.wikipedia.org/wiki/Cylinder Formula: 2 * pi * r * h @@ -255,9 +323,10 @@ def lateral_surface_cylinder(radius: float, height: float) -> float: def surface_area_torus(torus_radius: float, tube_radius: float) -> float: - """Calculate the Area of a Torus. + """ + Calculate the area of a torus. Wikipedia reference: https://en.wikipedia.org/wiki/Torus - :return 4pi^2 * torus_radius * tube_radius + Formula: 4 * pi^2 * torus_radius * tube_radius >>> surface_area_torus(1, 1) 39.47841760435743 >>> surface_area_torus(4, 3) @@ -291,6 +360,7 @@ def surface_area_torus(torus_radius: float, tube_radius: float) -> float: def area_rectangle(length: float, width: float) -> float: """ Calculate the area of a rectangle. + Formula: l * w >>> area_rectangle(10, 20) 200 @@ -319,6 +389,7 @@ def area_rectangle(length: float, width: float) -> float: def area_square(side_length: float) -> float: """ Calculate the area of a square. + Formula: s^2 >>> area_square(10) 100 @@ -339,6 +410,7 @@ def area_square(side_length: float) -> float: def area_triangle(base: float, height: float) -> float: """ Calculate the area of a triangle given the base and height. + Formula: (b * h) / 2 >>> area_triangle(10, 10) 50.0 @@ -366,8 +438,11 @@ def area_triangle(base: float, height: float) -> float: def area_triangle_three_sides(side1: float, side2: float, side3: float) -> float: """ - Calculate area of triangle when the length of 3 sides are known. - This function uses Heron's formula: https://en.wikipedia.org/wiki/Heron%27s_formula + Calculate the area of triangle given the length of 3 sides. + Wikipedia reference: https://en.wikipedia.org/wiki/Heron%27s_formula + This function uses Heron's formula: + s = (s1 + s2 + s3) / 2 + Formula: s(s-s1)(s-s2)(s-s3)^0.5 >>> area_triangle_three_sides(5, 12, 13) 30.0 @@ -412,9 +487,103 @@ def area_triangle_three_sides(side1: float, side2: float, side3: float) -> float return area +def area_triangle_side_angle_side( + side1: float, angle_in_degrees: float, side2: float +) -> float: + """ + Calculate the area of a triangle given 2 sides and the enclosing angle. + Wikipedia source: https://en.wikipedia.org/wiki/Area_of_a_triangle + Formula: s1 * s2 * sin(a) + + >>> area_triangle_side_angle_side(1, 30, 2) + 0.49999999999999994 + >>> area_triangle_side_angle_side(12, 60, 9) + 46.76537180435968 + >>> area_triangle_side_angle_side(0, 0, 0) + 0.0 + >>> area_triangle_side_angle_side(4.7, 37.5, 8.2) + 11.730832736998046 + >>> area_triangle_side_angle_side(-1, -2, -1) + Traceback (most recent call last): + ... + ValueError: area_triangle_side_angle_side() only accepts non-negative values + >>> area_triangle_side_angle_side(1, -2, 1) + Traceback (most recent call last): + ... + ValueError: area_triangle_side_angle_side() only accepts non-negative values + >>> area_triangle_side_angle_side(2, 183, 7) + Traceback (most recent call last): + ... + ValueError: Given angle does not form a triangle: must be less than 180 degrees + """ + if side1 < 0 or side2 < 0 or angle_in_degrees < 0: + raise ValueError( + "area_triangle_side_angle_side() only accepts non-negative values" + ) + if angle_in_degrees > 180: + raise ValueError( + "Given angle does not form a triangle: must be less than 180 degrees" + ) + area = side1 * side2 * sin(radians(angle_in_degrees)) / 2 + return area + + +def area_triangle_angle_side_angle( + angle_in_degrees1: float, side: float, angle_in_degrees2: float +) -> float: + """ + Calculate the area of a triangle given 2 angles and the enclosing side. + Wikipedia reference: https://en.wikipedia.org/wiki/Area_of_a_triangle + Formula: s^2 sin(a1)*sin(a2) / (2 * sin(a1 + a2)) + + >>> area_triangle_angle_side_angle(45, 10, 60) + 31.698729810778065 + >>> area_triangle_angle_side_angle(37.5, 7.8, 81.3) + 20.889315201325292 + >>> area_triangle_angle_side_angle(0, 0, 0) + Traceback (most recent call last): + ... + ValueError: Given angles do not form a triangle: sum must be between \ +0 and 180 degrees + >>> area_triangle_angle_side_angle(-1, -2, -1) + Traceback (most recent call last): + ... + ValueError: area_triangle_angle_side_angle() only accepts non-negative values + >>> area_triangle_angle_side_angle(1, -2, 1) + Traceback (most recent call last): + ... + ValueError: area_triangle_angle_side_angle() only accepts non-negative values + >>> area_triangle_angle_side_angle(92, 18, 99) + Traceback (most recent call last): + ... + ValueError: Given angles do not form a triangle: sum must be between \ +0 and 180 degrees + """ + if side < 0 or angle_in_degrees1 < 0 or angle_in_degrees1 < 0: + raise ValueError( + "area_triangle_angle_side_angle() only accepts non-negative values" + ) + + if not 0 < angle_in_degrees1 + angle_in_degrees2 < 180: + raise ValueError( + "Given angles do not form a triangle: sum must be between 0 and 180 degrees" + ) + + angle_in_rad1 = radians(angle_in_degrees1) + angle_in_rad2 = radians(angle_in_degrees2) + area = ( + (side**2) + * sin(angle_in_rad1) + * sin(angle_in_rad2) + / (2 * sin(angle_in_rad1 + angle_in_rad2)) + ) + return area + + def area_parallelogram(base: float, height: float) -> float: """ Calculate the area of a parallelogram. + Formula: base * height >>> area_parallelogram(10, 20) 200 @@ -443,6 +612,7 @@ def area_parallelogram(base: float, height: float) -> float: def area_trapezium(base1: float, base2: float, height: float) -> float: """ Calculate the area of a trapezium. + Formula: (base1 + base2) * height / 2 >>> area_trapezium(10, 20, 30) 450.0 @@ -481,12 +651,13 @@ def area_trapezium(base1: float, base2: float, height: float) -> float: """ if base1 < 0 or base2 < 0 or height < 0: raise ValueError("area_trapezium() only accepts non-negative values") - return 1 / 2 * (base1 + base2) * height + return (base1 + base2) * height / 2 def area_circle(radius: float) -> float: """ Calculate the area of a circle. + Formula: pi * r^2 >>> area_circle(20) 1256.6370614359173 @@ -506,7 +677,8 @@ def area_circle(radius: float) -> float: def area_ellipse(radius_x: float, radius_y: float) -> float: """ - Calculate the area of a ellipse. + Calculate the area of an ellipse. + Formula: pi * r1 * r2 >>> area_ellipse(10, 10) 314.1592653589793 @@ -537,6 +709,7 @@ def area_ellipse(radius_x: float, radius_y: float) -> float: def area_rhombus(diagonal_1: float, diagonal_2: float) -> float: """ Calculate the area of a rhombus. + Formula: d1 * d2 / 2 >>> area_rhombus(10, 20) 100.0 @@ -559,7 +732,7 @@ def area_rhombus(diagonal_1: float, diagonal_2: float) -> float: """ if diagonal_1 < 0 or diagonal_2 < 0: raise ValueError("area_rhombus() only accepts non-negative values") - return 1 / 2 * diagonal_1 * diagonal_2 + return diagonal_1 * diagonal_2 / 2 def area_reg_polygon(sides: int, length: float) -> float: @@ -576,12 +749,12 @@ def area_reg_polygon(sides: int, length: float) -> float: Traceback (most recent call last): ... ValueError: area_reg_polygon() only accepts integers greater than or equal to \ -three as number of sides +three as the number of sides >>> area_reg_polygon(-1, -2) Traceback (most recent call last): ... ValueError: area_reg_polygon() only accepts integers greater than or equal to \ -three as number of sides +three as the number of sides >>> area_reg_polygon(5, -2) Traceback (most recent call last): ... @@ -591,12 +764,12 @@ def area_reg_polygon(sides: int, length: float) -> float: Traceback (most recent call last): ... ValueError: area_reg_polygon() only accepts integers greater than or equal to \ -three as number of sides +three as the number of sides """ if not isinstance(sides, int) or sides < 3: raise ValueError( "area_reg_polygon() only accepts integers greater than or \ -equal to three as number of sides" +equal to three as the number of sides" ) if length < 0: raise ValueError( @@ -620,7 +793,7 @@ def surface_area_reg_prism(sides: int, edge: float, height: float) -> float: Traceback (most recent call last): ... ValueError: surface_area_reg_prism() only accepts integers greater than or equal \ -to three as number of sides +to three as the number of sides >>> surface_area_reg_prism(5, -2, 3) Traceback (most recent call last): ... @@ -635,12 +808,12 @@ def surface_area_reg_prism(sides: int, edge: float, height: float) -> float: Traceback (most recent call last): ... ValueError: surface_area_reg_prism() only accepts integers greater than or equal \ -to three as number of sides +to three as the number of sides """ if not isinstance(sides, int) or sides < 3: raise ValueError( "surface_area_reg_prism() only accepts integers greater than or \ -equal to three as number of sides" +equal to three as the number of sides" ) if edge < 0 or height < 0: raise ValueError( @@ -660,6 +833,8 @@ def surface_area_reg_prism(sides: int, edge: float, height: float) -> float: print(f"Square: {area_square(10) = }") print(f"Triangle: {area_triangle(10, 10) = }") print(f"Triangle: {area_triangle_three_sides(5, 12, 13) = }") + print(f"Triangle: {area_triangle_side_angle_side(5, 45, 13) = }") + print(f"Triangle: {area_triangle_angle_side_angle(5, 12, 103) = }") print(f"Parallelogram: {area_parallelogram(10, 20) = }") print(f"Rhombus: {area_rhombus(10, 20) = }") print(f"Trapezium: {area_trapezium(10, 20, 30) = }") @@ -670,13 +845,18 @@ def surface_area_reg_prism(sides: int, edge: float, height: float) -> float: print(f"Cuboid: {surface_area_cuboid(10, 20, 30) = }") print(f"Sphere: {surface_area_sphere(20) = }") print(f"Hemisphere: {surface_area_hemisphere(20) = }") + print(f"Hemisphere, lateral: {lateral_surface_area_hemisphere(20) = }") print(f"Cone: {surface_area_cone(10, 20) = }") print(f"Cone, lateral: {lateral_surface_cone(10, 20) = }") print(f"Conical Frustum: {surface_area_conical_frustum(10, 20, 30) = }") + print( + f"Conical Frustum, lateral: " + f"{lateral_surface_area_conical_frustum(10, 20, 30) = }" + ) print(f"Cylinder: {surface_area_cylinder(10, 20) = }") print(f"Cylinder, lateral: {lateral_surface_cylinder(10, 20) = }") print(f"Torus: {surface_area_torus(20, 10) = }") print(f"Equilateral Triangle: {area_reg_polygon(3, 10) = }") print(f"Square: {area_reg_polygon(4, 10) = }") - print(f"Reqular Pentagon: {area_reg_polygon(5, 10) = }") + print(f"Regular Pentagon: {area_reg_polygon(5, 10) = }") print(f"Regular Pentagonal Prism: {surface_area_reg_prism(5, 10, 15) = }") From a20dfc99734b14bcdf8f334565a15ba6224217f9 Mon Sep 17 00:00:00 2001 From: "arvid@12test.be" Date: Sat, 17 Oct 2026 13:07:08 +0200 Subject: [PATCH 2/7] minor layout change --- maths/area.py | 1 + 1 file changed, 1 insertion(+) diff --git a/maths/area.py b/maths/area.py index c8e154bdfcdf..c4d50a316984 100644 --- a/maths/area.py +++ b/maths/area.py @@ -1,5 +1,6 @@ """ Calculate the area of various geometric 2D and 3D shapes + Wikipedia reference: https://en.wikipedia.org/wiki/Area """ From 99d2e92caf83815a1e50bab02b9b2037aa98518e Mon Sep 17 00:00:00 2001 From: "arvid@12test.be" Date: Sat, 17 Oct 2026 17:44:21 +0200 Subject: [PATCH 3/7] minor layout change --- maths/area.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/area.py b/maths/area.py index c4d50a316984..f82f1300d6f0 100644 --- a/maths/area.py +++ b/maths/area.py @@ -537,8 +537,8 @@ def area_triangle_angle_side_angle( Wikipedia reference: https://en.wikipedia.org/wiki/Area_of_a_triangle Formula: s^2 sin(a1)*sin(a2) / (2 * sin(a1 + a2)) - >>> area_triangle_angle_side_angle(45, 10, 60) - 31.698729810778065 + >>> area_triangle_angle_side_angle(45, 10, 70) + 36.65769145387496 >>> area_triangle_angle_side_angle(37.5, 7.8, 81.3) 20.889315201325292 >>> area_triangle_angle_side_angle(0, 0, 0) From 4c5b0c72899dcc651c5afbb9a4f2b0b4d542268b Mon Sep 17 00:00:00 2001 From: "arvid@12test.be" Date: Sat, 17 Oct 2026 17:44:21 +0200 Subject: [PATCH 4/7] avoiding cross-platform float precision issue --- maths/area.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/area.py b/maths/area.py index c4d50a316984..f82f1300d6f0 100644 --- a/maths/area.py +++ b/maths/area.py @@ -537,8 +537,8 @@ def area_triangle_angle_side_angle( Wikipedia reference: https://en.wikipedia.org/wiki/Area_of_a_triangle Formula: s^2 sin(a1)*sin(a2) / (2 * sin(a1 + a2)) - >>> area_triangle_angle_side_angle(45, 10, 60) - 31.698729810778065 + >>> area_triangle_angle_side_angle(45, 10, 70) + 36.65769145387496 >>> area_triangle_angle_side_angle(37.5, 7.8, 81.3) 20.889315201325292 >>> area_triangle_angle_side_angle(0, 0, 0) From bf08c3bda710d13f342ab4b0a1cee91c23a59107 Mon Sep 17 00:00:00 2001 From: "arvid@12test.be" Date: Sat, 17 Oct 2026 17:51:13 +0200 Subject: [PATCH 5/7] Fixing floating point precision error in doctest --- maths/area.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/area.py b/maths/area.py index f82f1300d6f0..e00f3f76fe8d 100644 --- a/maths/area.py +++ b/maths/area.py @@ -537,8 +537,8 @@ def area_triangle_angle_side_angle( Wikipedia reference: https://en.wikipedia.org/wiki/Area_of_a_triangle Formula: s^2 sin(a1)*sin(a2) / (2 * sin(a1 + a2)) - >>> area_triangle_angle_side_angle(45, 10, 70) - 36.65769145387496 + >>> area_triangle_angle_side_angle(45, 10, 45) + 25.000000000000004 >>> area_triangle_angle_side_angle(37.5, 7.8, 81.3) 20.889315201325292 >>> area_triangle_angle_side_angle(0, 0, 0) From b61b4696d3796efacb2f9ced62ae71c4c4305a4c Mon Sep 17 00:00:00 2001 From: "arvid@12test.be" Date: Sat, 17 Oct 2026 17:54:58 +0200 Subject: [PATCH 6/7] Fixing floating point precision error in doctest --- maths/area.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/maths/area.py b/maths/area.py index e00f3f76fe8d..70d6a05898c2 100644 --- a/maths/area.py +++ b/maths/area.py @@ -537,8 +537,6 @@ def area_triangle_angle_side_angle( Wikipedia reference: https://en.wikipedia.org/wiki/Area_of_a_triangle Formula: s^2 sin(a1)*sin(a2) / (2 * sin(a1 + a2)) - >>> area_triangle_angle_side_angle(45, 10, 45) - 25.000000000000004 >>> area_triangle_angle_side_angle(37.5, 7.8, 81.3) 20.889315201325292 >>> area_triangle_angle_side_angle(0, 0, 0) From d2dd1890e78b2f8053d7a521c9509632e9fc4ed6 Mon Sep 17 00:00:00 2001 From: "arvid@12test.be" Date: Sat, 17 Oct 2026 18:42:10 +0200 Subject: [PATCH 7/7] Less inaccurate implementation of Taylor series. Clearer way to limit angle between -360 and 360 using modulo Avoid recalculating factorial(x) every iteration. Keep calculating until next term has no longer effect on the result. All existing doctests still succeed. --- maths/sin.py | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/maths/sin.py b/maths/sin.py index b06e6c9f1e5d..aa97088e1f8f 100644 --- a/maths/sin.py +++ b/maths/sin.py @@ -1,24 +1,25 @@ """ -Calculate sin function. - -It's not a perfect function so I am rounding the result to 10 decimal places by default. +Calculate the sine function, approximated by Taylor series expansion Formula: sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ... -Where: x = angle in randians. + Where: x = angle in randians. Source: https://www.homeschoolmath.net/teaching/sine_calculator.php - + Wikipedia reference: https://en.wikipedia.org/wiki/Taylor_series """ -from math import factorial, radians +from math import radians -def sin( - angle_in_degrees: float, accuracy: int = 18, rounded_values_count: int = 10 -) -> float: +def sin(angle_in_degrees: float, rounded_values_count: int = 10) -> float: """ - Implement sin function. + Calculate the sine function, approximated by Taylor series expansion + + For trigonometry calculations the expected precision is about 10 digits. + Python has floating precision of about 15 digits. + Using operation ** and / iteratively, precision is lost quickly + This method rounds to 10 digits by default, to be safe. >>> sin(0.0) 0.0 @@ -41,21 +42,25 @@ def sin( >>> sin(89.7) 0.9999862922 """ + # Simplify the angle to be between 360 and -360 degrees. - angle_in_degrees = angle_in_degrees - ((angle_in_degrees // 360.0) * 360.0) + angle_in_degrees %= 360.0 - # Converting from degrees to radians angle_in_radians = radians(angle_in_degrees) result = angle_in_radians - a = 3 - b = -1 - - for _ in range(accuracy): - result += (b * (angle_in_radians**a)) / factorial(a) + power_x = 3 + fac = -6 # - factorial(power_x) + result_old = 2 # any impossible sine result will do - b = -b # One positive term and the next will be negative and so on... - a += 2 # Increased by 2 for every term. + # Keep adding the next Tayler term until the result stops changing. + while True: + result += angle_in_radians**power_x / fac + power_x += 2 # Increased by 2 for every term. + fac *= -power_x * (power_x - 1) + if result == result_old: + break + result_old = result return round(result, rounded_values_count)