When I try to solve a equation python only uses integers - python

I am working on a new project, it is like a math site. I am trying to create a program that will solve equations.
It is working normally with simple equations for example x + 10 = 12, however when I try to do equations with exponents like x**2 + 3 = 5 it doesn't give me anything. I believe that this python code doesn't work with decimals.
Code in below
import math
def solve():
x = -1000
while x < 1001:
if x**2 + 1 == 4:
print("x = " + str(x))
x += 1
solve()
I expect the output to be 1.73205080757 and -1.73205080757.
However I get nothing (Because it couldn't find an answer).

You're expecting an answer that's between 1 & 2. You're starting at -1000 and incrementing by 1. So you'll go from -1000 to 0 to 1 to 2 to 3....skipping over your expected answer altogether.
You should be using something like: https://en.wikipedia.org/wiki/Newton%27s_method
(With floats i.e x=1.0)

Looking at your code, your minimal step is 1 (x was increased by x += 1), hence x can be only integer. There is no such integer can full-fill your condition x**2 + 1 == 4

this will only check integer values from x = - 1000 to x = 1000, ie it will ask is -1000 the answer? No, is -999 the answer? No etc, and never try 1.7 or 1.73 or 1.73...! The answer is a float not an integer, so the method as written can't possibly get it. You would need somehow to iterate closer and closer answers. This is a question of mathematical algorithm design I think, you can first look up math formulae how to approximate quadratic solutions (probably some 17th century mathematician did the formula!), then try convert this formula into Python. If you don't know about float, int, "duck typing" in Python difference, try googling this also may help you.

The code doesn't give nor will give the solution you expect because of two reasons:
The while loop increments x by 1 at each step, so there is no way x can be a float number. It will always be an integer.
The solution you expect for this case has infinite decimals, so even if x were a float, it could never be the desired value in order to solve the equation.
As a remark/suggestion, if you are trying to solve an equation in python, why don't you just create a function that give the result to an equation of the form: x^2 +a = b. The following code should be an example:
import numpy as np
def solve_prueba(a,b):
"""
The function solves a function of the form x^2 + a = b
"""
x = np.sqrt((b-a))
return x
This way is much more time effective rather than create a while loop has to pass over all the numbers with their infinite decimals to give the solution to a given equation.
Good luck!

It is not necessary to start at -1000 and go up to 1000 since you are looking for a value from 1 to 2. In your code, you increment with 1, which means that x will never be a decimal value. You could however increment with a very small number (e.g.) x += 0.0000000000001.
If you use this small increment, you should probably use math.isclose() instead of ==, because small float values tend to have some precision error. Like in your expected answer where you expect the outcome to be 1.73205080757 altough 1.73205080757**2 + 1 == 4.000000000003889 and not 4.
Using math.isclose((x**2 + 3), 4, rel_tol=1e-9) like this, it checks if the calculation from x**2 + 3 is somewhere close to 4 with a tolerance of 1e-9, which would output the values that you expect from this equation.
So for your code:
import math
def solve():
x = -1000
while x < 1001:
if math.isclose((x**2 + 1), 4, rel_rol=1e-9):
print("x = " + str(x))
x += 0.0000000000001
solve()

Related

Fastest way to find a number in an unknown range?

Sorry for the horrible title - I'm new to python and I'm not sure how to describe my question. So the question asks:
x plus 100 is a perfect square number, plus another 168 is also a perfect square number. Find x.
And here's my answer:
from math import sqrt
for x in range(-100,10000):
a=int(sqrt(x+100))
b=int(sqrt(x+100+168))
if (a*a!=x+100) or (b*b!=x+100+168):
continue
else:
print(x)
The problem is, I don't actually know the range. I only know that the number can't be smaller than -100, but the 10000 is only a random large number that I put in there. Is there a way for me to figure out a smaller range first? Or a way that I could make this faster?
If you want every solution in the range, this is a faster solution
for x in range(-100,10000):
if ((x+100)**.5).is_integer():
if ((x+268)**.5).is_integer():
print(x)
If only the first solution is required, you can add a break after the print statement.
There is an easily ascertainable upper bound to your problem: after a couple of numbers, the difference between perfect squares is much larger than 168. (Take a look at 100^2 and 101^2. The results are perfect squares about 200 apart. With this your number will be no larger than 10,000).
If you would like to speed up your problem, rather than checking if a number is square, you can check if by squaring numbers you can achieve a solution.
for x in range(0,100):
y=x
while y**2 - x**2 < 169 and y < 100:
y+=1
if y**2 - x**2 == 168:
print("Your number is: " + str(x**2 - 100))
Edit: code was broken, fixed. Running this gives you -99 (-99 + 100 is 1, is a perfect square, 1 + 168 is 169, which is 13^2), 21, 261, and 1581
Since the prompt assumes only one correct value of x, then there is no need to use a for loop, as we can just loop indefinitely using a while and no upper bound is known.
To check if the result of an operation is a whole number, we can check if the float and integer representation of the number are equal, i.e. int(num) == num.
>>> i = 1
>>> while True:
a, b = (i+100)**0.5, (i+268)**0.5
if int(a) == a and int(b) == b:
break
i += 1
>>> i
21
And if we check the quality of the result obtained, both results are whole numbers:
>>> (i+100)**0.5
11.0
>>> (i+268)**0.5
17.0

My pi approximation using the wallis' method doesn't work and I have no idea what's going on

I'm working in Python 3.7 and part of my assignment is to define Wallis' approach to approximating pi. I'm a maths student, not cut out for doing computer science and could really use some help, this is worth 40% of my grade in total and I can't do any more without defining this properly. Here is the code I have currently written:
def pi_wallis(n):
z=1
for k in range(n):
a=(2.0*k)//((2.0*k)-1.0)
b=(2.0*k)//((2.0*k)+1.0)
z*=(a*b)
return z
No matter the input I enter, I always get -0.0, can anyone shed any light as to why? I first had z=0 and have tried changing to z=2, still get -0.0
You are using integer division (//), which means that it's enough for one fraction (for example, 2/3 in the first iteration) to make the entire sequence 0.
You should use floating point division (/). It will also be clearer if you start the sequence from 1 and finish in n + 1 (since range is exclusive in the end).
def pi_wallis(n):
z = 1
for k in range(1, n + 1):
a = (2.0*k) / ((2.0*k)-1.0)
b = (2.0*k) / ((2.0*k)+1.0)
z *= a*b
return z

(python) solving transcendental equation

i need to solve following equation:
0 = -1 / x**0.5) - 2 * log((alpha * x**0.5) + beta)
alpha and beta are given, i just need to iterate x until a certain extent.
I'm not a great python programmer, but like to implement this one.
How might this be possible?
Best regards
The smartest to do would be to implement a solve function like Stanislav recommended. You can't just iterate over values of x until the equation reaches 0 due to Floating Point Arithmetic. You would have to .floor or .ceil your value to avoid an infinity loop. An example of this would be something like:
x = 0
while True:
x += 0.1
print(x)
if x == 10:
break
Here you'd think that x eventually reaches 10 when it adds 0.1 to 9.9, but this will continue forever. Now, I don't know if your values are integers or floats, but what I'm getting at is: Don't iterate. Use already built solve libraries.

Compute cosine without import math in python

I have a general idea of what to do, but my code is a mess and I'm having some trouble writing the algorithm in python for
cos(x)=1-(x^2)/2!+(x^4)/4!-(x^6)/6!+...
where x is in radians, computing cos(x) after 20 terms using while loops. So far what I've written is
x = float(input("Enter a value for x in degrees."))
x = (x*3.14159)/180
num_of_terms = 0
num = 1.0 ##numerator
y = 1.0
cosx = 1.0
while num_of_terms<1:
num_of_terms+=1
cosx = (num/y)
while num_of_terms>=1 and num_of_terms<=20:
num_of_terms+=1
num = num*(x*x)
y = y*num_of_terms*(num_of_terms-1)
if num_of_terms%2==0:
cosx = cosx+(-num/y)
else:
cosx = cosx+(num/y)
print(cosx)
I don't know how close I even am to being correct (I know it's wrong in at least some places so I can't properly check using math.cos) but the main question I have is how to switch from positive --> negative each term. The assignment states that I cannot use exponentiation operators, and before I was trying to do something like
x = float(input("Enter a value for x in degrees."))
x = (x*3.14)/180
num_of_terms = 0
y = 0
z = 1
cosx = ((-1)**(z-1))*((x**z)/(y))
so that the sign would switch for every other term. Now I have (as you can see above)
if num_of_terms%2==0:
cosx = cosx+(-num/y)
else:
cosx = cosx+(num/y)
which is incorrect, or at least the output I'm getting is incorrect.
You can handle the sign quite simply:
sign = -1
while num_of_terms <= 20:
sign = -sign
...
cosx += sign * num/y
You also have a structure problem in your loops: the first loop will terminate after one iteration ... except you've properly prevented it from getting back there. This is poor use of a loop.
Just initialize your variables before the loop, and then proceed as expected. Since you know how many times to iterate, use a for instead of a while.
cosx = (num/y)
for num_of_terms in range(1, 21):
...
You will find other computational problems in your code. Print out values each time through the loop to help track your execution and computations. At the start, just go through 3 or 4 times instead of 20.
For the factorial, keep a running product: it's like a running sum, except that you initialize it at 1, and multiply each time through the loop.
Okay; stick with the while. Now, manage your loop index and computational index. If you're doing term #1, what should the exponent be? What numbers do you multiply into y? Now identify the same values for term #2 and term #3.
More directly, stick in a print statement to track num_of_terms, y, and cosx. When you're doing term #3, what is y? It should be 4! or 6! (depending on how you number your terms), but it's not. Where did you go wrong?
Your problem is in the computation of the factorial. You're multiplying by num_of_terms, which only increments by one each time through the loop - you need something that changes by 2 each time through the loop. At least you're correctly multiplying both that number and the number-1.

Python Pi approximation

So I have to approximate Pi with following way: 4*(1-1/3+1/5-1/7+1/9-...). Also it should be based on number of iterations. So the function should look like this:
>>> piApprox(1)
4.0
>>> piApprox(10)
3.04183961893
>>> piApprox(300)
3.13825932952
But it works like this:
>>> piApprox(1)
4.0
>>> piApprox(10)
2.8571428571428577
>>> piApprox(300)
2.673322240709928
What am I doing wrong? Here is the code:
def piApprox(num):
pi=4.0
k=1.0
est=1.0
while 1<num:
k+=2
est=est-(1/k)+1/(k+2)
num=num-1
return pi*est
This is what you're computing:
4*(1-1/3+1/5-1/5+1/7-1/7+1/9...)
You can fix it just by adding a k += 2 at the end of your loop:
def piApprox(num):
pi=4.0
k=1.0
est=1.0
while 1<num:
k+=2
est=est-(1/k)+1/(k+2)
num=num-1
k+=2
return pi*est
Also the way you're counting your iterations is wrong since you're adding two elements at the time.
This is a cleaner version that returns the output that you expect for 10 and 300 iterations:
def approximate_pi(rank):
value = 0
for k in xrange(1, 2*rank+1, 2):
sign = -(k % 4 - 2)
value += float(sign) / k
return 4 * value
Here is the same code but more compact:
def approximate_pi(rank):
return 4 * sum(-float(k%4 - 2) / k for k in xrange(1, 2*rank+1, 2))
Important edit:
whoever expects this approximation to yield PI -- quote from Wikipedia:
It converges quite slowly, though – after 500,000 terms, it produces
only five correct decimal digits of π
Original answer:
This is an educational example. You try to use a shortcut and attempt to implement the "oscillating" sign of the summands by handling two steps for k in the same iteration. However, you adjust k only by one step per iteration.
Usually, in math at least, an oscillating sign is achieved with (-1)**i. So, I have chosen this for a more readable implementation:
def pi_approx(num_iterations):
k = 3.0
s = 1.0
for i in range(num_iterations):
s = s-((1/k) * (-1)**i)
k += 2
return 4 * s
As you can see, I have changed your approach a bit, to improve readability. There is no need for you to check for num in a while loop, and there is no particular need for your pi variable. Your est actually is a sum that grows step by step, so why not call it s ("sum" is a built-in keyword in Python). Just multiply the sum with 4 in the end, according to your formula.
Test:
>>> pi_approx(100)
3.1514934010709914
The convergence, however, is not especially good:
>>> pi_approx(100) - math.pi
0.009900747481198291
Your expected output is flaky somehow, because your piApprox(300) (should be 3.13825932952, according to your) is too far away from PI. How did you come up with that? Is that possibly affected by an accumulated numerical error?
Edit
I would not trust the book too much in regard of what the function should return after 10 and 300 iterations. The intermediate result, after 10 steps, should be rather free of numerical errors, indeed. There, it actually makes a difference whether you take two steps of k at the same time or not. So this most likely is the difference between my pi_approx(10) and the books'. For 300 iterations, numerical error might have severely affected the result in the book. If this is an old book, and they have implemented their example in C, possibly using single precision, then a significant portion of the result may be due to accumulation of numerical error (note: this is a prime example for how bad you can be affected by numerical errors: a repeated sum of small and large values, it does not get worse!).
What counts is that you have looked at the math (the formula for PI), and you have implemented a working Python version of approximating that formula. That was the learning goal of the book, so go ahead and tackle the next problem :-).
def piApprox(num):
pi=4.0
k=3.0
est=1.0
while 1<num:
est=est-(1/k)+1/(k+2)
num=num-1
k+=4
return pi*est
Also for real task use math.pi
Here is a slightly simpler version:
def pi_approx(num_terms):
sign = 1. # +1. or -1.
pi_by_4 = 1. # first term
for div in range(3, 2 * num_terms, 2): # 3, 5, 7, ...
sign = -sign # flip sign
pi_by_4 += sign / div # add next term
return 4. * pi_by_4
which gives
>>> for n in [1, 10, 300, 1000, 3000]:
... print(pi_approx(n))
4.0
3.0418396189294032
3.1382593295155914
3.140592653839794
3.1412593202657186
While all of these answers are perfectly good approximations, if you are using the Madhava-Leibniz Series than you should arrive at ,"an approximation of π correct to 11 decimal places as 3.14159265359" within in first 21 terms according to this website: https://en.wikipedia.org/wiki/Approximations_of_%CF%80
Therefore, a more accurate solution could be any variation of this:
import math
def estimate_pi(terms):
ans = 0.0
for k in range(terms):
ans += (-1.0/3.0)**k/(2.0*k+1.0)
return math.sqrt(12)*ans
print(estimate_pi(21))
Output: 3.141592653595635

Categories