passing a value calculated from one function to another - python

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)

Related

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

How to make this float precision without using print

I'm working on assignment, it's about numerical method regarding to trapezoidal rule
def trapezoidalRule(F,a,b,n):
h = float(b-a)/n
f_sum = 0
for i in range(1, n, 1):
x = a + i * h
f_sum = f_sum + f(x)
return h * (0.5 * f(a) + f_sum + 0.5 * f(b))
def f(x):
return x**3
a = 2
b = 10
n = 512
print('%.16f' %trapezoidalRule(f, a, b, n))
And the output is
2496.0058593750000000
My question is, how do i get a precission like that.. without using print('%.16f' %trapezoidalRule(f, a, b, n)). I want to append the result to the list, with exact value like that..
I already tried to google it, but i found nothing related to this problem, can somebody tell me the solution if i want to it ?
Change your return statement in trapezoidalRule to be formatted with 16 points of precision, do note that this is going to cause it to become a string as if you cast it back to float you'll lose the trailing 0's.
def trapezoidalRule(F,a,b,n):
h = float(b-a)/n
f_sum = 0
for i in range(1, n, 1):
x = a + i * h
f_sum = f_sum + f(x)
return format((h * (0.5 * f(a) + f_sum + 0.5 * f(b))), '.16f')
def f(x):
return x**3
a = 2
b = 10
n = 512
See the return line in trapezoidalRule so now if I print the exact output of trapezoidalRule like so: print(trapezoidalRule(f, a, b, n)) with no formatting I get:
2496.0058593750000000
To increase precision try using decimal module
import decimal
def trapezoidalRule(F,a,b,n):
h = decimal.Decimal(float(b-a)/n)
f_sum = 0
for i in range(1, n, 1):
x = a + i * h
f_sum = f_sum + f(x)
return h * (decimal.Decimal(0.5) * f(a) + f_sum + decimal.Decimal(0.5) * f(b))
def f(x):
return decimal.Decimal(x**3)

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)

Algorithm for integer solutions of a circle?

I am trying to search for integer solutions to the equation:
y^2 + x^2 = 2n^2
If I search this in wolfram alpha, they are all found almost immediately even for very large n. When I implemented a brute force approach it was very slow:
def psearch(n, count):
for x in range(0, n):
for y in range(0, n):
if x*x + y*y == 2*n**2:
print(x,y)
count += 1
return count
So I assume there is a much faster way to get all of the integer solutions to the equation above. How can I do this in python so that it will have much lower runtime?
Note: I have seen this question however it is about finding lattice points within a circle not the integer solutions to the equation of the circle. Also I am interested in finding the specific solutions not just the number of solutions.
Edit: I am still looking for something an order of magnitude faster. Here is an example: n=5 should have 12 integer solutions to find what those should be search this equation on Wolfram alpha.
Edit 2: #victor zen gave a phenomenal answer to the problem. Can anyone think of a way to optimize his solution further?
In your algorithm, you're searching for all possible y values. This is unnecessary. The trick here is to realize that
y^2 + x^2 = 2n^2
directly implies that
y^2 = 2n^2-x^2
so that means you only have to check that 2n^2-x^2 is a perfect square. You can do that by
y2 = 2*n*n - x*x
#check for perfect square
y = math.sqrt(y2)
if int(y + 0.5) ** 2 == y2:
#We have a perfect square.
Also, in your algorithm, you are only checking x values up to n. This is incorrect. Since y^2 will always be positive or zero, we can determine the highest x value we need to check by setting y^2 to its lowest value (i.e 0). Consequentially, we need to check all integer x values satisfying
x^2 <= 2n^2
which reduces to
abs(x) <= sqrt(2)*n.
Combine this with the optimization of only checking the top quadrant, and you have an optimized psearch of
def psearch(n):
count = 0
top = math.ceil(math.sqrt(2*n*n))
for x in range(1, top):
y2 = 2*n*n - x*x
#check for perfect square
y = math.sqrt(y2)
if int(y + 0.5) ** 2 == y2:
count+=4
return count
It is enough to search inside the first octant y>0, x<y (the four solutions (±n, ±n) are obvious and by symmetry a solution (x, y) yields 8 copies (±x, ±y), (±y, ±x)).
By monotonicity, for a given y there is at most one x. You can find it by following the circular arc incrementally, decreasing y then adjusting x. If you maintain the condition x²+y²≤2n² as tightly as possible, you get the code below which is optimized to use only elementary integer arithmetic (for efficiency, 2x is used instead of x).
x, y, d= 2 * n, 2 * n, 0
while y > 0:
y, d= y - 2, d - y + 1
if d < 0:
x, d= x + 2, d + x + 1
if d == 0:
print(x >> 1, '² + ', y >> 1, '² = 2.', n, '²', sep='')
Here are all solutions for n between 1 and 100:
7² + 1² = 2.5²
14² + 2² = 2.10²
17² + 7² = 2.13²
21² + 3² = 2.15²
23² + 7² = 2.17²
28² + 4² = 2.20²
31² + 17² = 2.25²
35² + 5² = 2.25²
34² + 14² = 2.26²
41² + 1² = 2.29²
42² + 6² = 2.30²
46² + 14² = 2.34²
49² + 7² = 2.35²
47² + 23² = 2.37²
51² + 21² = 2.39²
56² + 8² = 2.40²
49² + 31² = 2.41²
63² + 9² = 2.45²
62² + 34² = 2.50²
70² + 10² = 2.50²
69² + 21² = 2.51²
68² + 28² = 2.52²
73² + 17² = 2.53²
77² + 11² = 2.55²
82² + 2² = 2.58²
84² + 12² = 2.60²
71² + 49² = 2.61²
79² + 47² = 2.65²
85² + 35² = 2.65²
89² + 23² = 2.65²
91² + 13² = 2.65²
92² + 28² = 2.68²
98² + 14² = 2.70²
103² + 7² = 2.73²
94² + 46² = 2.74²
93² + 51² = 2.75²
105² + 15² = 2.75²
102² + 42² = 2.78²
112² + 16² = 2.80²
98² + 62² = 2.82²
97² + 71² = 2.85²
113² + 41² = 2.85²
115² + 35² = 2.85²
119² + 17² = 2.85²
123² + 3² = 2.87²
119² + 41² = 2.89²
126² + 18² = 2.90²
119² + 49² = 2.91²
133² + 19² = 2.95²
137² + 7² = 2.97²
124² + 68² = 2.100²
140² + 20² = 2.100²
You can optimize this algorithm maybe by considering only one quadrant only and the multiplying by 4.
import math
def psearch(n, count):
for x in range( 0 , 2*n + 1):
ysquare = 2*(n**2) - x * x
if (ysquare <0):
break
y = int(math.sqrt(ysquare))
if ysquare == y * y :
print(x,y)
count+=1
return count
print(psearch(13241324,0) * 4)
OUTPUT
(1269716, 18682964)
(1643084, 18653836)
(11027596, 15134644)
(12973876, 13503476)
(13241324, 13241324)
(13503476, 12973876)
(15134644, 11027596)
(18653836, 1643084)
(18682964, 1269716)
36

writing multiple data calculated from a function in the same file

I am trying to write a data calculated from this function in a file. But the function is called number of times. Say there are 9 numbers in another file and this function will calculate the root for each of those 9 numbers. These 9 roots from this function should be written in the same file. But the way I have done it here will write calculated root in the file but the next one will replace this in the file. There are other mathematical functions that are carried out for each of those 9 numbers before this function is called therefore the functions are called again and again separately.Is it possible to write them all in the same file? Thank you.
def Newton(poly, start):
""" Newton's method for finding the roots of a polynomial."""
x = start
poly_diff = poly_differentiate(poly)
n = 1
counter = 0
r_i = 0
cFile = open("curve.dat", "w")
while True:
if (n >= 0) and (n < 1):
break
x_n = x - (float(poly_substitute(poly, x)) / poly_substitute(poly_diff, x))
if x_n == x:
break
x = x_n # this is the u value corresponding to the given time
n -= 1
counter += 1
x = str(x)
cFile.write('\n' + x + '\n')
if r_i:
print "t(u) = ", (x, counter)
else:
print "t(u) = ", x
cFile.close
After following the suggestions I got I changed the code to the following:
def Newton(poly, start):
""" Newton's method for finding the roots of a polynomial."""
x = start
poly_diff = poly_differentiate(poly)
n = 1
counter = 0
while True:
if (n >= 0) and (n < 1):
break
x_n = x - (float(poly_substitute(poly, x)) / poly_substitute(poly_diff, x))
if x_n == x:
break
x = x_n # this is the u value corresponding to the given time
n -= 1
counter += 1
yield x
Bezier(x)
def Bezier(u_value) :
""" Calculating sampling points using rational bezier curve equation"""
u = u_value
p_u = math.pow(1 - u, 3) * 0.7 + 3 * u * math.pow(1 - u, 2) * 0.23 \
+ 3 * (1 - u) * math.pow(u, 2) * 0.1 + math.pow(u, 3) * 0.52
p_u = p_u * 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
p_u = p_u / d
yield p_u
plist = list (p_u)
print plist
I followed the same thing in the Bezier() function but plist is not created as it doesn't print anything. Please help. Thank you.
Your function does two things: It calculates the roots of a polynomial, and it writes the result to an output file. Functions should ideally do one thing.
So, try breaking this up into a function that receives a polynomial and returns a list containing the roots, and then just write that list to a file in one step.
The simplest way to modify your function would be to replace the lines
x = str(x)
cFile.write('\n' + x + '\n')
with
yield x
Then you can call your function like this:
roots = list(Newton(polynomial, start))
To understand this, read about generators. To write the resulting list to a file, you can use this code:
with open("curve.dat", "w") as output_file:
output_file.write("\n".join(str(x) for x in roots)
While I'm not completely understanding what you are asking I think the answer can be boiled down to:
Open the file in append mode, not in write mode. So instead of
cFile = open("curve.dat", "w")
do
cFile = open("curve.dat", "a")
why use yield in Bezier, it doesn't return multiple values, so you can change:
yield p_u
plist = list (p_u)
print plist
to:
print list(p_u)
return p_u

Categories