Horner's rule and direct method in python - python

I am trying to solve the following question. I have made codes for implanting the direct method and Horner's rule, which I believe I have done this correctly. However past that I am having some problems figuring out the rest. Looking for some help with this, all help is greatly appreciated!
Here is the code I have produced for Horner's rule, which I believe I have done correctly.
def poly_horner(A, x):
p = A[-1]
i = len(A) - 2
while i >= 0:
p = p * x + A[i]
i -= 1
return p
And here is the code I have produced for the direct method:
def poly_naive(A, x):
p = 0
for i, a in enumerate(A):
p += (x ** i) * a
return p
How can I put this code together and finish the rest?

Using global as suggested in the paper,
flops = 0
def add(x1, x2):
global flops
flops += 1
return x1 + x2
def multiply(x1, x2):
global flops
flops += 1
return x1 * x2
def poly_horner(A, x):
global flops
flops = 0
p = A[-1]
i = len(A) - 2
while i >= 0:
p = add(multiply(p, x), A[i])
i -= 1
return p
def poly_naive(A, x):
global flops
flops = 0
p = 0
for i, a in enumerate(A):
xp = a
for _ in range(i):
xp = multiply(xp, x)
p = add(p, xp)
return p
To run the above code, for example:
>>> poly_horner([1,2,3,4,5], 2)
129
>>> print(flops)
8
Compare to numpy's polyval:
>>> import numpy as np
>>> np.polyval([5,4,3,2,1], 2)
129

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).

McLaurin series for cosine

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

I'm implementing 'XOR' function and it fails for

import numpy as np
def AND(x1, x2):
x = np.array(x1,x2)
w = np.array(0.5,0.5)
b = -0.7
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
def NAND(x1, x2):
x = np.array([x1, x2])
w = np.array([-0.5, -0.5])
b = 0.7
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
print(NAND(1,0))
print(NAND(1,1))
def OR(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.2
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
print(OR(0,1))
print(OR(0,0))
def XOR(x1, x2):
s1 = NAND(x1,x2)
s2 = OR(x1,x2)
y = AND(s1,s2)
return y
print(XOR(0,1))
I completed AND, OR, NAND gate. and they all works really precisely as i expected. And finally i tried to make a XOR logic by combining NAND, OR, AND in sequence... But here comes the traceback error message i 've never expected like below. What should be modified to fulfill my original purpose.
TypeError: Cannot interpret '1' as a data type
The first (and second) line of AND is not the same as the first line of OR and NAND. That's the problem. See it?
Ironic that you had unit tests for OR and NAND, but not for AND.

How do I write a Python code for partial fraction decomposition without using "apart"?

So I am very unexperienced with Python, I know basically nothing, and our teacher gave us the task to write a code that makes a partial fraction decomposition with this function:
I don't really know how to start or even how to define that function. I tried this at first: `
def function(x):
a = (x^4)-(3*x^2)+x+5
b = (x^11)-(3*x^10)-(x^9)+(7*x^8)-(9*x^7)+(23*x^6)-(11*x^5)-(3*x^4)-(4*x^3)-(32*x^2)-16
return a/b
But our maths script says that we need to split up the denominator and then make a system of equations out of it and solve it.
So I was thinking about defining each part of the function itself and then make a function somehow like a = 7*x and use it like f(x) = b/a^7 if this works but I don't really know. We are unfortunately not allowed to use "apart" which I think is a sympy-function?
Thank you so much in advance!
Sincerely, Phie
Addition: So after a few hours of trying I figured this. But I am very sure that this is not the way to do it. Also it tells me that variable l is not defined in z and I am sure that all the others aren't as well. I don't know what to do.
def function(x):
global a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v
a = (x^4)-(3*x^2)+x+5
b = 11
c = 10
d = 9
e = 8
f = 7
g = 6
h = 5
i = 4
j = 3
k = 2
l = x**b
m = 3*x**c
n = x**d
o = 7*x**e
p = 9*x**f
q = 23*x**g
r = 11*x**h
s = 3*x**i
t = 4*x**j
u = 32*x**k
v = 16
return a/(l-m-n+o-p+q-r-s-t-u-v)
print("We are starting the partial fraction decomposition with this
function: (x^4)-(3*x^2)+x+5 / (x^11)-(3*x^10)-(x^9)+(7*x^8)-(9*x^7)+
(23*x^6)-(11*x^5)-(3*x^4)-(4*x^3)-(32*x^2)-16")
z = l-m-n+o-p+q-r-s-t-u-v
while c >= 0:
c = c-1
z = z-l
while d >= 0:
d = d-1
z = z-m
while e >= 0:
e = e-1
z = z-n
while f >= 0:
f = f-1
z = z+o
while g >= 0:
g = g-1
z = z-p
while h >= 0:
h = h-1
z = z+q
while i >= 0:
i = i-1
z = z-r
while j >= 0:
j = j-1
z = z-s
while k >= 0:
k = k-1
z = z-t
print(z)
Since I just solved this myself, here's some input:
Let poly = function() for your function, although be careful to replace ^ with **. Include both from sympy import * and from sympy.abc import a, b, c, d, e, f, g, h, i, j, k, x.
Using factor(exp) you can find all the roots of your function, use these to define the 11 terms term_1 = a/(x-2), term_2 = b/(x2-)**2, ... , term_6 = (f*x + g)/(x**2 +1), ..., term_8 = (j*x + k)/(x**2 + 1) (you get the gist). Define your_sum = term_1 + ... + term_8, eq = Eq(your_sum, poly)
Define the variable your_sum = sum(term_1, ..., term_8), and use solve_undetermined_coeffs(eq, [a,b, ..., k], x))) to get the result.

Calculate a polynomial

I want to calculate a polynomial on x value. I tried to write
a function that takes as argument an array of integer and integer x
the function will returns the value of the polynomial in x.
def pol(L, x):
P = None
for i in L:
P = L[0] * (x ** 0) + L[1] * (x ** 1) + L[2] * (x ** 2)
return P
L = [0, 2, 4]
x = 3
print(pol(L, x))
I also tried
def pol(L, x):
P = None
for i in L:
j = 0
P = sum(i * (x ** j))
j += 0
return P
L = [0, 2, 4]
x = 3
print(pol(L, x))
It will return 42 for this example.
I don't know how to increment.
Thanks
Building up on your attempts, one straightforward way to get the polynomial would be the following:
def poly(p, x):
val = 0
for i, pp in enumerate(p):
val += pp * x**i
return val
There are faster and more elegant ways to do this, though. I'd strongly encourage you to use numpy.polyval() for efficiency.
Note that for the numpy implementation, p[0] is the highest order polynomial while for the example shown here, p[0] is the lowest order!
p = [0, 2, 4]
x = 3
poly(p, x)
>> 42
import numpy as np
poly(p, x) == np.polyval(p[::-1], x)
>> True

Categories