Skip to content

Commit 1158294

Browse files
Create maths/pi_generator.py (TheAlgorithms#8666)
* Create pi_generator.py * Update pi_generator.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pi_generator.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pi_generator.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pi_generator.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pi_generator.py * Update pi_generator.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated commentary on line 28, added math.pi comparison & math.isclose() test * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Removed # noqa: E501 * printf() added as recommended by cclaus --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 458debc commit 1158294

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

maths/pi_generator.py

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
def calculate_pi(limit: int) -> str:
2+
"""
3+
https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80
4+
Leibniz Formula for Pi
5+
6+
The Leibniz formula is the special case arctan 1 = 1/4 Pi .
7+
Leibniz's formula converges extremely slowly: it exhibits sublinear convergence.
8+
9+
Convergence (https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80#Convergence)
10+
11+
We cannot try to prove against an interrupted, uncompleted generation.
12+
https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80#Unusual_behaviour
13+
The errors can in fact be predicted;
14+
but those calculations also approach infinity for accuracy.
15+
16+
Our output will always be a string since we can defintely store all digits in there.
17+
For simplicity' sake, let's just compare against known values and since our outpit
18+
is a string, we need to convert to float.
19+
20+
>>> import math
21+
>>> float(calculate_pi(15)) == math.pi
22+
True
23+
24+
Since we cannot predict errors or interrupt any infinite alternating
25+
series generation since they approach infinity,
26+
or interrupt any alternating series, we are going to need math.isclose()
27+
28+
>>> math.isclose(float(calculate_pi(50)), math.pi)
29+
True
30+
31+
>>> math.isclose(float(calculate_pi(100)), math.pi)
32+
True
33+
34+
Since math.pi-constant contains only 16 digits, here some test with preknown values:
35+
36+
>>> calculate_pi(50)
37+
'3.14159265358979323846264338327950288419716939937510'
38+
>>> calculate_pi(80)
39+
'3.14159265358979323846264338327950288419716939937510582097494459230781640628620899'
40+
41+
To apply the Leibniz formula for calculating pi,
42+
the variables q, r, t, k, n, and l are used for the iteration process.
43+
"""
44+
q = 1
45+
r = 0
46+
t = 1
47+
k = 1
48+
n = 3
49+
l = 3
50+
decimal = limit
51+
counter = 0
52+
53+
result = ""
54+
55+
"""
56+
We will avoid using yield since we otherwise get a Generator-Object,
57+
which we can't just compare against anything. We would have to make a list out of it
58+
after the generation, so we will just stick to plain return logic:
59+
"""
60+
while counter != decimal + 1:
61+
if 4 * q + r - t < n * t:
62+
result += str(n)
63+
if counter == 0:
64+
result += "."
65+
66+
if decimal == counter:
67+
break
68+
69+
counter += 1
70+
nr = 10 * (r - n * t)
71+
n = ((10 * (3 * q + r)) // t) - 10 * n
72+
q *= 10
73+
r = nr
74+
else:
75+
nr = (2 * q + r) * l
76+
nn = (q * (7 * k) + 2 + (r * l)) // (t * l)
77+
q *= k
78+
t *= l
79+
l += 2
80+
k += 1
81+
n = nn
82+
r = nr
83+
return result
84+
85+
86+
def main() -> None:
87+
print(f"{calculate_pi(50) = }")
88+
import doctest
89+
90+
doctest.testmod()
91+
92+
93+
if __name__ == "__main__":
94+
main()

0 commit comments

Comments
 (0)