Time - Gravity Fall program - python

I am trying to create a program that will work out how long it will take for something to hit the ground when dropped from a particular height and it uses the known quadratic formula. The program appears to be doing what I want of it until it reaches line 7 where there is a math issue I beleive involving sqrt. Can anybody help?
So far I have come up with...
v = float(input())
lowerSum = 2*(-4.9)
upperSum1 = -4*(-4.9)
upperSum2 = (upperSum1)*(11000)
upperSum3 = (v)**2 - (upperSum2)
from math import sqrt
upperSum4 = (v) - sqrt(upperSum3)
t = (upperSum4) / (lowerSum)
print (t)
When I run the program it states that there is a math domain error; I'm new to programming and I do not know what this means.
I am trying to print out the value of t.

You misread the formula (bottom of page).
Specifically, you are applying the minus sign after v**2 twice:
First you apply it here (incorrectly, as if it was a negative sign):
upperSum1 = -4*(-4.9)
Then you apply it again here (correctly, as a minus symbol).
upperSum3 = (v)**2 - (upperSum2)
upperSum1 should be:
upperSum1 = 4*(-4.9)

The 'math domain error' is telling you that you've passed the sqrt function a value that is outside it's "domain". The domain of the sqrt function is the positive numbers. At some point upperSum3 becomes negative, which makes the sqrt rather unhappy, so it throws an error at you.
You could fix this by adding an if statement to change what your code does if upperSum3 is less than 0, for example:
if upperSum3 < 0:
#do something other than take the sqrt
else:
upperSum4 = (v) - sqrt(upperSum3)

Just going a bit deeper into the problem by doing the math...
v = float(input())
lowerSum = -9.8
upperSum1 = 19.6
upperSum2 = 215600
upperSum3 = (v)**2 - (215600)
from math import sqrt
upperSum4 = (v) - sqrt(upperSum3)
t = (upperSum4) / (lowerSum)
print (t)
So you have to have the square of v in line 5 be more than 215600 for the equation to not return a negative number to sqrt(), which is what is causing the error.
V has to be greater than 465 for the upperSum3 to be positive, and by running various numbers, it never actually becomes positive, so there's definitely something wrong with the equation you are using, or the set-up itself.
Without knowing the formula myself (which I can't find) there's no way for me to tell which part of the code is actually wrong.

import math
v=float(input())
t=float()
Result1=float(v-(math.sqrt(float(v**2)-float(4*(-4.9))*(11000))))
Result2=float(2*(-4.9))
t=float(Result1/Result2)
print(t)
This works. However, I'm new to python and was having trouble with my results converting to an integer. So.... if my use of "float" seems excessive, it's cause it is :-) For a good half an hour I was trying to perform all of the calculations on one line but gave up and broken it down. If anyone has a better solution that performs the calculation on one line I'm all ears.

Related

Basic troubles with python maths

Working on a very simple program to learn python.
The goal is to calculate Euler's constant with the user inputing a value for the equations precision (p). The program should use that variable in the equation (1+1/p)^(10^p).
I am currently having two problems with this program. The first of which is that the program will work if I first define p as p=10**p, then use the equation (1+1/p)**p which brings us to the second problem.
The second problem is that any (user inputted) value for p that exceeds 14 will not work at all. (15 returns 3.035035... and higher values just return 1.0)
I am extremely new to python and its math syntax and that may be my problem.
Thank you all for any help
Code in question:
import math
p=None
e=None
p = int(input('Please enter a whole number precison multiplier (1-14):'))
p=10.0**p
print((1.0+1.0/p)**p)
I guess you're trying to approximate e. The formula is (1 + 1/p)^p as p -> infinity, not (1 + 1/p)^(10^p). This should work:
p = int(input('Please enter a whole number precison multiplier:'))
print((1 + 1/p)**(p))

Writing a double sum in Python

I am new to StackOverflow, and I am extremely new to Python.
My problem is this... I am needing to write a double-sum, as follows:
The motivation is that this is the angular correction to the gravitational potential used for the geoid.
I am having difficulty writing the sums. And please, before you say "Go to such-and-such a resource," or get impatient with me, this is the first time I have ever done coding/programming/whatever this is.
Is this a good place to use a "for" loop?
I have data for the two indices (n,m) and for the coefficients c_{nm} and s_{nm} in a .txt file. Each of those items is a column. When I say usecols, do I number them 0 through 3, or 1 through 4?
(the equation above)
\begin{equation}
V(r, \phi, \lambda) = \sum_{n=2}^{360}\left(\frac{a}{r}\right)^{n}\sum_{m=0}^{n}\left[c_{nm}*\cos{(m\lambda)} + s_{nm}*\sin{(m\lambda)}\right]*\sqrt{\frac{(n-m)!}{(n+m)!}(2n + 1)(2 - \delta_{m0})}P_{nm}(\sin{\lambda})
\end{equation}
(2) Yes, a "for" loop is fine. As #jpmc26 notes, a generator expression is a good alternative to a "for" loop. IMO, you'll want to use numpy if efficiency is important to you.
(3) As #askewchan notes, "usecols" refers to an argument of genfromtxt; as specified in that documentation, column indexes start at 0, so you'll want to use 0 to 3.
A naive implementation might be okay since the larger factorial is the denominator, but I wouldn't be surprised if you run into numerical issues. Here's something to get you started. Note that you'll need to define P() and a. I don't understand how "0 through 3" relates to c and s since their indexes range much further. I'm going to assume that each (and delta) has its own file of values.
import math
import numpy
c = numpy.getfromtxt("the_c_file.txt")
s = numpy.getfromtxt("the_s_file.txt")
delta = numpy.getfromtxt("the_delta_file.txt")
def V(r, phi, lam):
ret = 0
for n in xrange(2, 361):
for m in xrange(0, n + 1):
inner = c[n,m]*math.cos(m*lam) + s[n,m]*math.sin(m*lam)
inner *= math.sqrt(math.factorial(n-m)/math.factorial(n+m)*(2*n+1)*(2-delta[m,0]))
inner *= P(n, m, math.sin(lam))
ret += math.pow(a/r, n) * inner
return ret
Make sure to write unittests to check the math. Note that "lambda" is a reserved word.

Computing the circumference, area, and ratio of circumference to area of a circle

Studying for a CS test and basically I have to follow instructions that are similar to this.
Write a program, that is a file containing a main function followed by
a call to the main, and name the program ratio.py. The basic structure
of the program should look like this:
def main():
...
return
main() where the ellipsis indicates where you should place the code that performs following computations:
-you should prompt the user for an integer value corresponding to the
radius of a circle. Do this with code similar to:
radius = int(input("circle radius? "))
compute the circumference of the circle using the formula c = 2 πr where r is the radius and c is the circumference. Use the value of
3.14159 for π
compute the area of the circle using the formula c = πr2
print the ratio of the circumference to the area (the ratio of a to b is a divided by b)
Here is what I have written so far. I got the circumference and the area but how do I get it to make a ratio between the two and print the ratio.
def main():
radius = int(input("circle radius? "))
pi = 3.14159
r = radius
c = 2*pi*r
print(2*pi*r)
a = pi*r*r
print(pi*r*r)
ratio = c / a
return(ratio)
print("the ratio of the circumference to the area is",ratio)
main()
The ultimate goal is to get something like this:
$ python3 ratio.py
circle radius? 2
the ratio of the circumference to the area is ????
where ???? is replaced by the actual ratio.
You are extremely close to solving this. Here are a couple ideas to help you finish it:
import statements should generally go at the top of the file, not inside a function. They will work in the function, but it is poor form. This was probably not taught in class, but you get used to seeing particular patterns as you read other people's code.
As a matter of style, Python generally uses capital letters for names of constants, so PI=3.14159 is more common than pi=3.14159. This is minor and works either way. It is a good style to adhere to, since it will help make your code match others' code.
You need to calculate the area using the equation given to you: a = PI*r*r (NOTE - the original question incorrectly uses 'c' for the area. 'c' is the circumference.)
You need to return c/a, which is the ratio that was requested.
You probably need to print out the return value for testing. You can do that by storing the value returned by main() in a variable and then printing it.
Here is how to return a value from your main() function:
def main():
...
return c/a
ratio = main()
print(ratio)
# or...
print("The ratio is:", ratio)
it's odd that you do c = (2*math.pi*r) when you have pi declared as a variable above two lines. Doing math.pi goes to python's math library and digs up a more accurate version of pi. For all intents and purposes, you are just completely not using that pi variable.
see http://docs.python.org/2/library/math.html for more information.
Furthermore, you do the same computation twice.
c = 2*math.pi*r
return(2*math.pi*r)
c just ends up being garbage collected (which is to say, the computer does the computation then INTO THE TRASH IT GOES) and never being used. It would be better to simply return c
For scoping issues, which I'm sure you wouldn't really know about as a beginner, put import math above your main function, unindented.
just for future reference though, SO tends to be for isolated problems that you have spotted in code; not for a full code review. A more acceptable question would be along the lines of "my function is returning an unexpected value", not "my function is not working"

Prevent Rounding to Zero in Python

I have a program meant to approximate pi using the Chudnovsky Algorithm, but a term in my equation that is very small keeps being rounded to zero.
Here is the algorithm:
import math
from decimal import *
getcontext().prec = 100
pi = Decimal(0.0)
C = Decimal(12/(math.sqrt(640320**3)))
k = 0
x = Decimal(0.0)
result = Decimal(0.0)
sign = 1
while k<10:
r = Decimal(math.factorial(6*k)/((math.factorial(k)**3)*math.factorial(3*k)))
s = Decimal((13591409+545140134*k)/((640320**3)**k))
x += Decimal(sign*r*s)
sign = sign*(-1)
k += 1
result = Decimal(C*x)
pi = Decimal(1/result)
print Decimal(pi)
The equations may be clearer without the "decimal" terms.
import math
pi = 0.0
C = 12/(math.sqrt(640320**3))
k = 0
x = 0.0
result = 0.0
sign = 1
while k<10:
r = math.factorial(6*k)/((math.factorial(k)**3)*math.factorial(3*k))
s = (13591409+545140134*k)/((640320**3)**k)
x += sign*r*s
sign = sign*(-1)
k += 1
result = C*x
pi = 1/result
print pi
The issue is with the "s" variable. For k>0, it always comes to zero. e.g. at k=1, s should equal about 2.1e-9, but instead it is just zero. Because of this all of my terms after the first =0. How do I get python to calculate the exact value of s instead of rounding it down to 0?
Try:
s = Decimal((13591409+545140134*k)) / Decimal(((640320**3)**k))
The arithmetic you're doing is native python - by allowing the Decimal object to perform your division, you should eliminate your error.
You can do the same, then, when computing r.
A couple of comments.
If you are using Python 2.x, the / returns an integer result. If you want a Decimal result, you convert at least one side to Decimal first.
math.sqrt() only return ~16 digits of precision. Since your value for C will only be accurate to ~16 digits, your final result will only be accurate to 16 digits.
If you're doing maths in Python 2.x, you should probably be putting this line into every module:
from __future__ import division
This changes the meaning of the division operator so that it will return a floating point number if needed to give a (closer to) precise answer. The historical behaviour is for x / y to return an int if both x and y are ints, which usually forces the answer to be rounded down.
Returning a float if necessary is generally regarded as a better way to handle division in a language like Python where duck typing is encouraged, since you can just worry about the value of your numbers rather than getting different behaviour for different types.
In Python 3 this is in fact the default, but since old programs relied on the historical behaviour of the division operator it was felt the change was too backwards-incompatible to be made in Python 2. This is why you have to explicitly turn it on with the __future__ import. I would recommend always adding that import in any module that might be doing any mathematics (or just any module at all, if you can be bothered). You'll almost never be upset that it's there, but not having it there has been the cause of a number of obscure bugs I've had to chase.
I feel that the problem with 's' is that all terms are integers, thus you are doing integer maths. A very simple workaround, would be to use 3.0 in the denominator. It only takes one float in the calculation to get a float returned.

fsolve always returning the guess/estimate

I'm using scipy's optimize.fsolve function for the first time to find the roots to an equation. The problem is that whatever number I use as the guess/estimate value is what I get back as my answer (to within about 8 decimal places). When using full_output=True, I get the exitflag to be '1', which is supposed to mean that 'The solution converged', which to the best of my understanding should mean that the output is indeed a root of the equation.
I know there are a finite number of distinct roots (that are spaced out), as when I graph the equation I can see them. Also, fsolve fails (gives error exitflags) when I input the starting point to be in a range which should return a undefined values (divide by zero, square root of a negative value). But besides that it always return the starting point as the root.
I tested fsolve with a very simple equation and it worked fine, so I know that I'm importing everything I need and should be using fsolve correctly. I also tried messing around with some of the input arguments, but I don't understand them very well and nothing seemed to change).
Below is the relevant code (E is the only variable, everything else has a non-zero value):
def func(E):
s = sqrt(c_sqr * (1 - E / V_0))
f = s / tan(s) + sqrt(c_sqr - s**2)
return f
guess = 3
fsolve(func, guess)
which just outputs '3' and says 'The solution converged.', even though the closest solutions should be at about 2.8 and 4.7.
Does anyone have any idea how to fix this and get a correct answer (using fsolve)?
I think your equation doesn't do what you think it does. For one thing, when I try it, it doesn't return the guess; it returns a number close to the guess. It's very unstable and that seems to be confusing fsolve. For example:
>>> V_0 = 100
>>> c_sqr = 3e8 ** 2
>>> guess = 5
>>> fsolve(func, guess)
array([ 5.00000079])
This is not 5. It is not even 5 within machine precision. It is also not a root of the equation:
>>> func(5.00000079)
2114979.3239706755
But the behavior of the equation is pretty unpredictable anyway:
>>> func(5.0000008)
6821403.0196130127
>>> func(5.0000006)
-96874198.203683496
So obviously there's a zero crossing somewhere around there. I'd say take a good look at your equation. Make sure you are specifying tan's argument in radians, for instance.
Did you try changing your function to something really trivial? Like this:
#!/usr/bin/python
from scipy.optimize import fsolve
def func(E):
# s = sqrt(c_sqr * (1 - E / V_0))
# f = s / tan(s) + sqrt(c_sqr - s**2)
f = E**2 -3.
return f
guess = 9
sol=fsolve(func, guess)
print sol, func(sol)
For me the code above does converge to where it should.
Also, in the code you've provided --- what are c_str and V_0? If in fact your function depends on more than one variable, and you're treating all of them but one as constant parameters, then use the args argument of the fsolve, like this:
#!/usr/bin/python
from scipy.optimize import fsolve
from numpy import sqrt
def func(E,V_0):
#s = sqrt(c_sqr * (1 - E / V_0))
#f = s / tan(s) + sqrt(c_sqr - s**2)
f = E**2 -V_0
return f
VV=4.
guess = 9
sol=fsolve(func, guess, args=(VV))
print sol, func(sol,VV)

Categories