McLaurin series for cosine - python

I want to make a cosine function that relies on the McLaurin expansion on cosine.. but it doesn't work: it should return me '-1.0..something' but it returns me another value, please can you guys help me??
code:
import math
def _cos(n:float,prec:int):
a = []
k = 0.0
for x in range(prec):
a.append(
((-1)**k)*((n**(2*k+1))/(2*k+1))
)
k+=1
z = 0
for x in a:
z+=x
return z
pi = math.pi
print(_cos(pi,200))
print(math.cos(pi))

As I can see you don't have the good formula.
((-1)**k)*((n**(2*k+1))/(2*k+1))
it's n**(2*n)
then you need to divide it by the factorial of 2n
4! = 4 * 3 * 2 * 1
2n! = 2n * 2n-1 * 2n-2 * 2n-3 ...

your formula of mac laurin is false: see maclaurin cosinus
in your loop, you do a mixture with the pow (x is the pow not k)
your correct code will be:
def _cos(n:float,prec:int):
a = []
for x in range(prec):
a.append(
((-1)**x)*((n**(2*x))/factorial(2*x))
)
z = 0
for x in a:
z+=x
return z
pi = 3.14159265359
print(_cos(pi,200))
print(math.cos(pi))
but if you do that with a precision of 200, you will be an overflow
try with 10 is already best.
i suggest you to use the precicion not from a number of iteration but from the difference between old value and new value like this :
def _cos(n:float,prec:float):
k = 0
cosine_x = 0.0
while True:
old = cosine_x + (pow(-1, k) * pow(n, 2 * k) / factorial(2 * k))
#print(old)
if 0 < abs(old - cosine_x) < prec:
return old
cosine_x = old
k += 1
pi = 3.14159265359
print(_cos(pi,0.000000000000001))
print(cos(pi))

You were not updating k, as you used x for the range and you were missing the factorial function in the division. Try with precison as 20, but 200 is too high.
Try the following code:
import math
def _cos(n:float,prec:int):
a = []
k = 0
for k in range(prec):
a.append(
((-1)**k) * ((n**(2*k))) /
math.factorial(2*k)
)
z = 0
for x in a:
z += x
return z

Related

Why does my program for the Chudnovsky algorithm give the wrong result?

I am trying to code the Chudnovsky algorithm in python. However, when I run my code, it gives me a very small number (-5.051212624421025e-55) which is not pi. I am in middle school, and I don't know anybody that can help me. What am I doing wrong?
Here is a link to the Chudnovsky formula: https://levelup.gitconnected.com/generating-the-value-of-pi-to-a-known-number-of-decimals-places-in-python-e93986bb474d
Here is my code:
import math
def fact(exi):
memory = exi
for i in range(1, exi):
memory *= i
return memory
k = 10
s = 0
for i in range(0, k):
a = -1^k
b = fact(6*k)
c = (545140134*k) + 13591409
d = fact(3*k)
e = (fact(k))^3
f = (3 * k) + 3/2
g = math.pow(640320, f)
numerator = (a*b*c)
denominator = (d*e*f)
s += (numerator / denominator)
s *= 12
print(1 / s)
Here is my updated code:
import math
def fact(exi):
memory = exi
for i in range(1, exi):
memory *= i
return memory
k = 17
s = 0
for i in range(1, k):
a = (-1)**i
b = fact(6*i)
c = (545140134*i) + 13591409
d = fact(3*i)
e = (fact(i))**3
f = (3 * i) + 3/2
g = math.pow(640320, f)
num = (a*b*c)
den = (d*e*g)
s += (num / den)
s *= 12
print(1 / s)
I see two mistakes:
When comparing with the formula shown on Wikipedia, it looks like you should use the iteration variable i (named q in the formula) where you currently use k in the loop. In your code k is the upper bound for i.
The exponentiation operator in Python is **, not ^ (which is bitwise XOR).

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.

I want to change this def by using lambda

import random
def Calculate_Pi(total):
inside = 0
for i in range(0, total):
x2 = random.random() ** 2
y2 = random.random() ** 2
if x2 + y2 <= 1.0:
inside += 1
pi = (float(inside) / total) * 4
return pi
I want to change this def by using lambda
import random as r
total = int(input("total : "))
pi = lambda inside : float(len([x for x in range(total) if r.random()**2 + r.random()**2 <= 1.0]) / total) * 4
print(pi(total))
this is my code but i don't know this is right and i want to know any better code
Not sure why you want this but you can do it this way
calculate_pi = lambda total:(sum(((random.random()**2) + (random.random()**2)) <=1.0 for _ in range(total)) / total) * 4
print(calculate_pi(5)) # 3.2

How to calculate sum of terms of Taylor series of sin(x) without using inner loops or if-else?

I can't use inner loops
I can't use if-else
I need to compute the following series:
x - x^3/3! + x^5/5! - x^7/7! + x^9/9! ...
I am thinking something like the following:
n =1
x =0.3
one=1
fact1=1
fact2=1
term =0
sum =0
for i in range(1, n+1, 2):
one = one * (-1)
fact1 = fact1*i
fact2 = fact2*i+1
fact = fact1*fact2
x = x * x
term = x/fact
sum = sum + term
But, I am finding hard times in keeping the multiplications of both fact and x.
You want to compute a sum of terms. Each term is the previous term mutiplied by -1 * x * x and divided by n * (n+1). Just write it:
def func(x):
eps = 1e-6 # the expected precision order
term = x
sum = term
n = 1
while True:
term *= -x * x
term /= (n+1) * (n+2)
if abs(term) < eps: break
sum += term
n += 2
return sum
Demo:
>>> func(math.pi / 6)
0.4999999918690232
giving as expected 0.5 with a precision of 10e-6
Note: the series is the well known development of the sin function...
Isn't that a Taylor series for sin(x)? And can you use list comprehension? With list comprehension that could be something like
x = 0.3
sum([ (-1)**(n+1) * x**(2n-1) / fact(2n-1) for n in range(1, numOfTerms)])
If you can't use list comprehension you could simply loop that like this
x=0.3
terms = []
for n in range(1, numberOfTerms):
term = (-1)**(n+1)*x**(2n-1)/fact(2n-1)
terms.append(term)
sumOfTerms = sum(terms)
Then calculating the factorial by recursion:
def fact(k):
if (k == 1):
return n
else:
return fact(k-1)*k
Calcualting the factorial using Striling's approximation:
fact(k) = sqrt(2*pi*k)*k**k*e**(-k)
No if-else here nor inner loops. But then there will be precision errors and need to use math lib to get the constants or get even more precision error and use hard coded values for pi and e.
Hope this can help!
n = NUMBER_OF_TERMS
x = VALUE_OF_X
m = -1
sum = x # Final sum
def fact(i):
f = 1
while i >= 1:
f = f * i
i = i - 1
return f
for i in range(1, n):
r = 2 * i + 1
a = pow (x , r)
term = a * m / fact(r);
sum = sum + term;
m = m * (-1)

passing a value calculated from one function to another

I have been doing python programming for my project and I have just started. This might be another trivial question. I have this code in which I need to use a value calculated in the function poly_root() which is x. That value should be used as u in the bezier() function. After poly_root() function it should go to bezier() function with its calculated value. I dont know if I am doing it in the correct way. There is no error but it doesnt print t from the bezier() function. Thank you very much.
import copy
import math
poly = [[-0.8,3], [0.75,2], [-0.75,1], [0.1,0]]
def poly_diff(poly):
""" Differentiate a polynomial. """
newlist = copy.deepcopy(poly)
for term in newlist:
term[0] *= term[1]
term[1] -= 1
return newlist
def poly_apply(poly, x):
""" Apply values to the polynomial. """
sum = 0.0 # force float
for term in poly:
sum += term[0] * (x ** term[1])
return sum
def poly_root(poly, start, n, r_i):
""" Returns a root of the polynomial, with a starting value."""
poly_d = poly_diff(poly)
x = start # starting guess value
counter = 0
while True:
if (n >= 0) and (n < 1):
break
x_n = x - (float(poly_apply(poly, x)) / poly_apply(poly_d, x))
if x_n == x:
break
x = x_n # this is the u value corresponding to the given time which will be used in bezier equation
n -= 1
counter += 1
if r_i:
#print [x, counter])
return [x, counter]
else:
#print x
return x
bezier(x)
def bezier(value) :
""" Calculates control points using rational bezier curve equation"""
u = value
w = 5
t = math.pow(1-u,3) * points[0][0] + 3 * u * math.pow(1-u,2) * points[1][0] \
+ 3 * (1-u) * math.pow(u,2) * points[2][0] + math.pow(u,3) * points[3][0]
t = t * w
d = math.pow(1-u,3) * w + 3 * u * w * math.pow(1-u,2) + 3 * (1-u) * w \
* math.pow(u,2) + math.pow(u,3) * w
t = t / d
print t
if __name__ == "__main__" :
poly_root(poly, 0.42, 1, 0)
In this part of code:
if r_i:
#print [x, counter])
return [x, counter]
else:
#print x
return x
bezier(x)
bezier(x) is unreachable. You need to rewrite it.
It would be better for poly_root to return the same type of thing in both situations (i.e. a list with two elements) ...
if r_i:
return [x, counter]
else:
return [x, None]
Then at the bottom, you can have ...
if __name__ == "__main__" :
x, counter = poly_root(poly, 0.42, 1, 0)
if counter is None: # I don't know if this is what you intended with your code.
bezier(x)

Categories