mirror of
https://hub.njuu.cf/TheAlgorithms/Python.git
synced 2023-10-11 13:06:12 +08:00
Create maths/pi_generator.py (#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>
This commit is contained in:
parent
458debc237
commit
11582943a5
94
maths/pi_generator.py
Normal file
94
maths/pi_generator.py
Normal file
@ -0,0 +1,94 @@
|
||||
def calculate_pi(limit: int) -> str:
|
||||
"""
|
||||
https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80
|
||||
Leibniz Formula for Pi
|
||||
|
||||
The Leibniz formula is the special case arctan 1 = 1/4 Pi .
|
||||
Leibniz's formula converges extremely slowly: it exhibits sublinear convergence.
|
||||
|
||||
Convergence (https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80#Convergence)
|
||||
|
||||
We cannot try to prove against an interrupted, uncompleted generation.
|
||||
https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80#Unusual_behaviour
|
||||
The errors can in fact be predicted;
|
||||
but those calculations also approach infinity for accuracy.
|
||||
|
||||
Our output will always be a string since we can defintely store all digits in there.
|
||||
For simplicity' sake, let's just compare against known values and since our outpit
|
||||
is a string, we need to convert to float.
|
||||
|
||||
>>> import math
|
||||
>>> float(calculate_pi(15)) == math.pi
|
||||
True
|
||||
|
||||
Since we cannot predict errors or interrupt any infinite alternating
|
||||
series generation since they approach infinity,
|
||||
or interrupt any alternating series, we are going to need math.isclose()
|
||||
|
||||
>>> math.isclose(float(calculate_pi(50)), math.pi)
|
||||
True
|
||||
|
||||
>>> math.isclose(float(calculate_pi(100)), math.pi)
|
||||
True
|
||||
|
||||
Since math.pi-constant contains only 16 digits, here some test with preknown values:
|
||||
|
||||
>>> calculate_pi(50)
|
||||
'3.14159265358979323846264338327950288419716939937510'
|
||||
>>> calculate_pi(80)
|
||||
'3.14159265358979323846264338327950288419716939937510582097494459230781640628620899'
|
||||
|
||||
To apply the Leibniz formula for calculating pi,
|
||||
the variables q, r, t, k, n, and l are used for the iteration process.
|
||||
"""
|
||||
q = 1
|
||||
r = 0
|
||||
t = 1
|
||||
k = 1
|
||||
n = 3
|
||||
l = 3
|
||||
decimal = limit
|
||||
counter = 0
|
||||
|
||||
result = ""
|
||||
|
||||
"""
|
||||
We will avoid using yield since we otherwise get a Generator-Object,
|
||||
which we can't just compare against anything. We would have to make a list out of it
|
||||
after the generation, so we will just stick to plain return logic:
|
||||
"""
|
||||
while counter != decimal + 1:
|
||||
if 4 * q + r - t < n * t:
|
||||
result += str(n)
|
||||
if counter == 0:
|
||||
result += "."
|
||||
|
||||
if decimal == counter:
|
||||
break
|
||||
|
||||
counter += 1
|
||||
nr = 10 * (r - n * t)
|
||||
n = ((10 * (3 * q + r)) // t) - 10 * n
|
||||
q *= 10
|
||||
r = nr
|
||||
else:
|
||||
nr = (2 * q + r) * l
|
||||
nn = (q * (7 * k) + 2 + (r * l)) // (t * l)
|
||||
q *= k
|
||||
t *= l
|
||||
l += 2
|
||||
k += 1
|
||||
n = nn
|
||||
r = nr
|
||||
return result
|
||||
|
||||
|
||||
def main() -> None:
|
||||
print(f"{calculate_pi(50) = }")
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user