Python pi calculation? - python

I am a python beginner and I want to calculate pi. I tried using the Chudnovsky algorithm because I heard that it is faster than other algorithms.
This is my code:
from math import factorial
from decimal import Decimal, getcontext
getcontext().prec=100
def calc(n):
t= Decimal(0)
pi = Decimal(0)
deno= Decimal(0)
k = 0
for k in range(n):
t = ((-1)**k)*(factorial(6*k))*(13591409+545140134*k)
deno = factorial(3*k)*(factorial(k)**3)*(640320**(3*k))
pi += Decimal(t)/Decimal(deno)
pi = pi * Decimal(12)/Decimal(640320**(1.5))
pi = 1/pi
return pi
print calc(25)
For some reason this code yields the vakue of pi up to only 15 decimals as compared with the acceptable value. I tried to solve this by increasing the precision value; this increases the number of digits, but only the first 15 are still accurate. I tried changing the way it calculates the algorithm and it didn't work either. So my question is, is there something that can be done to this code to make it much more accurate or would I have to use another algorithm? I would appreciate help with this because I don't know how to operate with so many digits in python. I would like to be able to control the number of (correct) digits determined and displayed by the program -- whether 10, 100, 1000, etc.

It seems you are losing precision in this line:
pi = pi * Decimal(12)/Decimal(640320**(1.5))
Try using:
pi = pi * Decimal(12)/Decimal(640320**Decimal(1.5))
This happens because even though Python can handle arbitrary scale integers, it doesn't do so well with floats.
Bonus
A single line implementation using another algorithm (the BBP formula):
from decimal import Decimal, getcontext
getcontext().prec=100
print sum(1/Decimal(16)**k *
(Decimal(4)/(8*k+1) -
Decimal(2)/(8*k+4) -
Decimal(1)/(8*k+5) -
Decimal(1)/(8*k+6)) for k in range(100))

For people who come here just to get a ready solution to get arbitrary precision of pi with Python (source with a couple of edits):
import decimal
def pi():
"""
Compute Pi to the current precision.
Examples
--------
>>> print(pi())
3.141592653589793238462643383
Notes
-----
Taken from https://docs.python.org/3/library/decimal.html#recipes
"""
decimal.getcontext().prec += 2 # extra digits for intermediate steps
three = decimal.Decimal(3) # substitute "three=3.0" for regular floats
lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
while s != lasts:
lasts = s
n, na = n + na, na + 8
d, da = d + da, da + 32
t = (t * n) / d
s += t
decimal.getcontext().prec -= 2
return +s # unary plus applies the new precision
decimal.getcontext().prec = 1000
pi = pi()

from decimal import *
#Sets decimal to 25 digits of precision
getcontext().prec = 25
def factorial(n):
if n<1:
return 1
else:
return n * factorial(n-1)
def plouffBig(n): #http://en.wikipedia.org/wiki/Bailey%E2%80%93Borwein%E2%80%93Plouffe_formula
pi = Decimal(0)
k = 0
while k < n:
pi += (Decimal(1)/(16**k))*((Decimal(4)/(8*k+1))-(Decimal(2)/(8*k+4))-(Decimal(1)/(8*k+5))-(Decimal(1)/(8*k+6)))
k += 1
return pi
def bellardBig(n): #http://en.wikipedia.org/wiki/Bellard%27s_formula
pi = Decimal(0)
k = 0
while k < n:
pi += (Decimal(-1)**k/(1024**k))*( Decimal(256)/(10*k+1) + Decimal(1)/(10*k+9) - Decimal(64)/(10*k+3) - Decimal(32)/(4*k+1) - Decimal(4)/(10*k+5) - Decimal(4)/(10*k+7) -Decimal(1)/(4*k+3))
k += 1
pi = pi * 1/(2**6)
return pi
def chudnovskyBig(n): #http://en.wikipedia.org/wiki/Chudnovsky_algorithm
pi = Decimal(0)
k = 0
while k < n:
pi += (Decimal(-1)**k)*(Decimal(factorial(6*k))/((factorial(k)**3)*(factorial(3*k)))* (13591409+545140134*k)/(640320**(3*k)))
k += 1
pi = pi * Decimal(10005).sqrt()/4270934400
pi = pi**(-1)
return pi
print "\t\t\t Plouff \t\t Bellard \t\t\t Chudnovsky"
for i in xrange(1,20):
print "Iteration number ",i, " ", plouffBig(i), " " , bellardBig(i)," ", chudnovskyBig(i)

Related

Errors in Directly vs Recursively Calculating a given Fibonacci Number

I was bored at work and was playing with some math and python coding, when I noticed the following:
Recursively (or if using a for loop) you simply add integers together to get a given Fibonacci number. However there is also a direct equation for calculating Fibonacci numbers, and for large n this equation will give answers that are, frankly, quite wrong with respect to the recursively calculated Fibonacci number.
I imagine this is due to rounding and floating point arithmetic ( sqrt(5) is irrational after all), and if so can anyone point me into a direction on how I could modify the fibo_calc_direct function to return a more accurate result?
Thanks!
def fib_calc_recur(n, ii = 0, jj = 1):
#n is the index of the nth fibonacci number, F_n, where F_0 = 0, F_1 = 1, ...
if n == 0: #use recursion
return ii
if n == 1:
return jj
else:
return(fib_calc_recur(n -1, jj, ii + jj))
def fib_calc_direct(n):
a = (1 + np.sqrt(5))/2
b = (1 - np.sqrt(5))/2
f = (1/np.sqrt(5)) * (a**n - b**n)
return(f)
You could make use of Decimal numbers, and set its precision depending on the magninute of n
Not your question, but I'd use an iterative version of the addition method. Here is a script that makes both calculations (naive addition, direct with Decimal) for values of n up to 4000:
def fib_calc_iter(n):
a, b = 0, 1
if n < 2:
return n
for _ in range(1, n):
a, b = b, a + b
return b
from decimal import Decimal, getcontext
def fib_calc_decimal(n):
getcontext().prec = n // 4 + 3 # Choose a precision good enough for this n
sqrt5 = Decimal(5).sqrt()
da = (1 + sqrt5) / 2
db = (1 - sqrt5) / 2
f = (da**n - db**n) / sqrt5
return int(f + Decimal(0.5)) # Round to nearest int
# Test it...
for n in range(1, 4000):
x = fib_calc_iter(n)
y = fib_calc_decimal(n)
if x != y:
print(f"Difference found for n={n}.\nNaive method={x}.\nDecimal method={y}")
break
else:
print("No differences found")

Trigonometric Functions: How do I write Sine and Cosine function's code without using `math` module?

I have been writing code for a module I am making for my Discord Bot. I have been trying not to use any module as it is not helping in in importing stuff. So I thought I should write the code myself for both of them.
The problem here is that I don't really know how do we make them. I couldn't find them anywhere on the net as everywhere I only saw the use of math module which I don't want to use.
I don't know how do I work with them, so I want some help.
Thank You! :)
Using Taylor expansion you get an approximation up to the desired precision.
http://hyperphysics.phy-astr.gsu.edu/hbase/tayser.html
def pow(base, exponent):
return base ** exponent
def faktorial(n):
value = float(1)
for i in range(1, n+1):
value = value * i
return value
def cos(x):
x = x * 3.14/180
value = 1
sign = -1
n = 200 # precision
i = 2
while i < n:
value = value + (pow(x, i)/faktorial(i) * sign)
i = i + 2
sign = sign * -1
return value
def sin(x):
x = x * 3.14/180
value = x
sign = -1
n = 200 # precision
i = 3
while i < n:
value = value + (pow(x, i)/faktorial(i) * sign)
i = i + 2
sign = sign * -1
return value
pi = 3.1415926535897932384626433832795028841971 # Value of constant pi
def f(n): # Factorial Function
if n == 1 or n == 0:
return 1
else:
return n * f(n - 1)
def deg(x):
rad = x * pi/180
return rad
def sin(x): # Taylor Expansion of sinx
k = 0
sinx = 0
while x >= pi:
x -= pi
if pi > x > pi / 2:
x = pi - x
while k < 15:
sinx += (-1)**k * x**(2*k + 1) / f(2*k + 1)
k += 1
return sinx
def cos(x):
cosx = sin(pi / 2 - x)
return cosx
I improved the code now. Now it gives you accurate results of up to 14 decimal places. Also instead of writing full Taylor expression formula, I used a while loop to do that. While loop here acts as a summation function of maths. I also shorten the code inside cos(x). Instead of writing Taylor's expression here, I used a conversion formula of sinx to cosx. Which reduces the calculation process. I made a little change in the code. Now you can calculate sinx of huge number too with the same accuracy.

Python Alternating + and - between fractions

I am trying to use the Nilakantha Pi Series formula and a for loop to calculate pi depending on how far into the calculation the user chooses the iterations to be. Here is the website that shows this infinite formula: https://www.mathsisfun.com/numbers/pi.html. I want to display the correct answer for iterations greater than 1, but only the first iteration shows the correct answer. Here is what I have so far:
def for_loop(number):
n = 4
pi = 3
for i in range(1, number + 1):
den = (n-2) * (n-1) * n
if (number % 2 == 0):
pi -= (4 / den)
print(pi)
else:
pi += (4 / den)
print(pi)
n = n + 2
The immediate problem is that you are checking if number, not i, is even or odd. But you don't need any such checks. You just have to alternate the numerator between 4 and -4.
def for_loop(number):
n = 4
pi = 3
num = 4
for _ in range(number):
den = (n-2) * (n-1) * n
pi += num/den
print(pi)
num *= -1
n += 2
or
from itertools import cycle
def for_loop(number):
n = 4
pi = 3
for num in cycle([4, -4]):
den = (n-2)*(n-1)*n
pi += num/den
print(pi)
n += 2
or even
from itertools import cycle, count
def for_loop(number):
pi = 3
for num, n in zip(cycle([4,-4]), count(4, 2)):
den = (n-2)*(n-1)*n
pi += num/den
print(pi)
You have to rework the condition of %2
def for_loop(number):
n = 4
pi = 3
for i in range(1, number + 1):
den = (n-2) * (n-1) * n
if (i % 2 == 0):# replace number by i , its alternating between even/uneven, however number is all the time the same.
pi -= (4 / den)
else:
pi += (4 / den)
print(pi)
n = n + 2
This is another way of doing it by using the reduce() function of the functools module, to solve the operation in the denominator of the fraction. To change the sign (-1 or 1) for each iteration, you can just multiply it by -1.
from functools import reduce
def nilakantha(n):
i, sign, start, base, stop = 1, 1, 2, 3, 4
res = base
while i < n and n > 1:
res += sign * (4 / reduce(lambda x, y: x * y, range(start, stop + 1)))
sign *= -1
start = stop
stop = start + 2
i += 1
return res
Example output
>>> nilakantha(524)
3.141592655327371

python3 calculate N digits of PI python cut the long number

i need to write a script that get input from client of an number and i need to print back the PI number until client number
for example: client number is 52 --> 3.14159265358979323846264338327950288419716939937510
so far i write this:
sum = 0
for i in range(1, 1001):
sum += ((-1)**(i+1))*4 / ((i + i)*(i + i + 1)*(i + i + 2))
print(sum)
the issue is that python showing to me only the 17 decimals digits, and i expect to see the 1000 decimal digits.
there is a way to showing all the decimal digits based on the inputed range?
it's for school task, so i need to write is as simple as it can be.
I do not think it is possible to get a a float value with a 1000point precision.
Check https://stackoverflow.com/a/54967370/11152011 to calculate pi up to n-precision
You can then use the "decimal" library to use the string as a number.
The calculation of pi was taken from the above link.
import decimal
DIGITS = 1000
def pi_digits(x):
k,a,b,a1,b1 = 2,4,1,12,4
while x > 0:
p,q,k = k * k, 2 * k + 1, k + 1
a,b,a1,b1 = a1, b1, p*a + q*a1, p*b + q*b1
d,d1 = a/b, a1/b1
while d == d1 and x > 0:
yield int(d)
x -= 1
a,a1 = 10*(a % b), 10*(a1 % b1)
d,d1 = a/b, a1/b1
digits = [str(n) for n in list(pi_digits(DIGITS))]
str_pi='{}.{}'.format(digits.pop(0), "".join(digits)
context = decimal.Context(prec=100)
decimal.setcontext(context)
pi = decimal.Decimal(str_pi)
print(pi+5)
print(pi*20)
I don't know how accurate is this but for a small class assignment i guess do the following:
num=52 #input
pi=22/7;
print('{:.{}f}'.format(pi, num))

Writing a Python function to calculate Pi

newbie here:
Just learning Python and this one has me pooped. It's coming up with a function for manually computing Pi, the Madhava way. - Also known as exercise #16 from here: http://interactivepython.org/courselib/static/thinkcspy/Functions/thinkcspyExercises.html
Can somebody take a look at my discombobulated and overly complex code and tell me if I'm missing something? Much thanks. (look at the equation on the wiki page first, otherwise my code will make no sense - well, it still may not.)
import math
def denom_exp(iters):
for i in range(0, iters):
exp = 3^iters
return exp
def base_denom(iters):
for i in range(0, iters):
denom = 1 + 2*iters
return denom
def myPi(iters):
sign = 1
pi = 0
for i in range(0, iters):
pi = pi + sign*(1/((base_denom(iters))*denom_exp(iters)))
sign = -1 * sign
pi = (math.sqrt(12))*pi
return pi
thisisit = myPi(10000)
print(thisisit)
Try this code, manually computing Pi, the Madhava way.
import math
def myPi(iters):
sign = 1
x = 1
y = 0
series = 0
for i in range (iters):
series = series + (sign/(x * 3**y))
x = x + 2
y = y + 1
sign = sign * -1
myPi = math.sqrt(12) * series
return myPi
print(myPi(1000))

Categories