I'm very new to python programming and to this site. I'm currently working on a problem and can't seem to understand the error.
import math
# Problem number 5.
A5 = 5
B5 = 0
C5 = 6.5
# Root1
x9 = (-B5 + math.sqrt(B5**2 - 4*A5*C5))/(2*A5)
# Root2
x10 = (-B5 + math.sqrt(B5**2 - 4*A5*C5))/(2*A5)
# Print solution
print()
print('Problem #5')
print('Root 1: ',x9)
print('Root 2: ',x10)
I get this after i run it:
x9 = (-B5 + math.sqrt(B5**2 - 4*A5*C5))/(2*A5)
ValueError: math domain error
I did the problem on paper and got an answer for both...
If you got an answer, it must have been a complex number (which are not included by default in Python). Look at the line math.sqrt(B5**2 - 4*A5*C5).
This evaluates as so:
math.sqrt(B5**2 - 4*A5*C5)
math.sqrt(0**2 - 4*5*6.5)
math.sqrt(0 - 130)
math.sqrt(-130)
The function math.sqrt doesn't find complex roots. You should use cmath.sqrt instead, as that does (this will require importing cmath at the start of your program).
Using cmath, I get this result:
Problem #5
Root 1: 1.1401754250991378j
Root 2: 1.1401754250991378j
(where j is the square root of -1).
Related
First of all; english is not my main language so bare in mind. (The text in the script is in norwegian, I will try to translate as well as possible)
I am trying to create a python script that solves a second degree equation or a quadratic? equation I think. If i understand it correctly I should use cmath module to be able to solve complex roots, however, I havent got that far in my class yet and it is my task to only use math module and return a answer that looks something like this (if the roots are complex): "There is no real solution".
Also, when using normal math module I get returned a "math domain error" when trying to for example put a = 6, b = 11 and c = 32.
Thank you in advance.
Edward
Trying to use a if/elif/else thingy, have tried cmath (it returns a waaaay to long and unreadable answer)
My code is here under this (hopefully I have pasted it correctly, sorry in advance:
#Importerer math
import math
print("Programmet skal løse andregradslikningen ")
print("ax^2 + bx + c = 0 ved hjelp av abc-formelen")
print("Skriv inn verdiene for a, b og c.")
a = float(input('a = '))
b = float(input('b = '))
c = float(input('c = '))
d = (b**2) - (4*a*c)
sol1 = (-b+math.sqrt(d))/(2*a)
sol2 = (-b-math.sqrt(d))/(2*a)
if d < 0:
print("Likningen har ingen løsning")
elif d==0:
print(f"Løsning x = {-b/(2*a)}")
else:
print("Løsningen er")
print(f"x = {sol1}, og x= {sol2}")
You have to check if d is negative before you try to call math.sqrt(d), so you don't get an error.
d = (b**2) - (4*a*c)
if d < 0:
print("Likningen har ingen løsning")
elif d==0:
print(f"Løsning x = {-b/(2*a)}")
else:
sol1 = (-b+math.sqrt(d))/(2*a)
sol2 = (-b-math.sqrt(d))/(2*a)
print("Løsningen er")
print(f"x = {sol1}, og x= {sol2}")
I am trying to convert these rate equations to python code, I have made I lot of research but can't seem to get any clear path to follow to achieve this, please any help will be appreciated
This is a newly updated code....i wrote using the quide from Tom10.....please what do you think?
import numpy as np
# import numpy as sum # not necessary, just for convenience, and replaces the builtin
# set N_core value
N_CORE = 0
# set the initial conditions appropriately (you need to set these correctly)
N = np.ones(8)
r = np.ones((8, 8))
dN = np.zeros(8) # the value here is not important for your equations
# set constant for equation 1
R_P1abs37 = 20
F_P1 = 20
R_P1abs47 = 40
W_3317 = 1.0
# set constant for equation 2
W_6142 = 90
W_5362 = 80
# Set you constants appropriately for equation 3
R_P2abs35 = 30
F_P2 = 40
R_L2se34 = 50
F_L2 = 90
# equation 4 constants
W_2214 = 20
#equation 5 constants
R_P1abs13 = 30
R_L2se32 = 20
F_L1 = 10
# equation 1 formular
dN[7] =sum(r[7,:]*N[7]) + (R_P1abs37*F_P1) + (R_P1abs47*F_P1) + (W_3317*N[3]**2)
# equation 2 formular
dN[6] = (r[7,6]*N[7]) - sum(r[6,:]*N[6]) - (W_6142*N[6]*N[1]) + (W_5362*N[5]*N[3])
#equation 3 formular
dN[5] = sum(r[:,5]*N) - sum(r[5,:]*N[5]) + R_P2abs35*F_P2 - R_L2se34*F_L2 - W_5362*N[5]*N[3]
# equation 4 formular
dN[4] = sum(r[:,4]*N) - sum(r[4,:]*N[4]) - (R_P1abs47*F_P1) + (R_L2se34*F_L2) + (W_2214*N[2]**2)+ (W_6142*N[6]*N[1])
#equation 5 formular
dN[3] = sum(r[:,3]*N) - sum(r[3,:]*N[3]) + (R_P1abs13*F_P1) - (R_P1abs37*F_P1) - (R_P2abs35*F_P2)
-(R_L2se32*F_L1) - ((2*W_3317)*N[3]**2) - (W_5362*N[5]*N[3])
#equation 6 formular
dN[2] = sum(r[:,2]*N) - (r[2,1]*N[2]) + (R_L2se32*F_L1) - ((2*W_2214)*N[2]**2) + (W_6142*N[6]*N[1])+(W_5362*N[5]*N[3])
#equation 7 formular
dN[1] = sum(r[:,1] * N) - (R_P1abs13*F_P1) + (W_2214*N[2]**2) + (W_3317+N[3]**2) - (W_6142+N[6]*N[1])
#equation for N CORE
N_CORE = sum(dN)
print(N_CORE)
Here is list of relevant issues based on your question and comments:
Usually if the summation is over i, then everything without an i subscript is constant for that sum. (Mathematically these constant terms can just be brought out of the sum; so the first equation is a bit odd where the N_7 could be moved out of the sum but I think they're keeping it in to show the symmetry with the other equations which all have an r*N term).
The capitol sigma symbol (Σ) means you need to do a sum, which you can do in a loop, but both Python list and numpy have a sum function. Numpy has the additional advantage that multiplication is interpreted as multiplication of the individual elements, making the expression easier. So for a[0]*[b0] + a[1]*b[1] + a[2]*b[2] and numpy arrays is simply sum(a*b) and for Python lists it's sum([a[i]*b[i] for in range(len(a))]
Therefore using numpy, the setup and your third equation would look like:
import numpy as np
import numpy.sum as sum # not necessary, just for convenience, and replaces the builtin
# set the initial conditions appropriately (you need to set these correctly)
N = np.ones(7, dtype=np.float)
# r seems to be a coupling matrix, and should be set according to your system
r = np.ones((7, 7), dtype = np.float)
# the values for dN are not important for your equations because dN only appears on the left side of the equations, so we just make a place to store the results
dN = np.zeros(7, dtype=np.float)
# Set you constants appropriate.y
R_P2abs35 = 1.0
F_P2 = 1.0
R_L2se34 = 1.0
F_L2 = 1.0
W_5362 = 1.0
dN[5] = sum(r[:,5]*N) - sum(r[5,:]*N[5]) + R_P2abs35*F_P2 - R_L2se34*F_L2 - W_5362*N[5]*N[3]
Note that although the expressions in the sums look similar, the first is essentially a dot product between two vectors and the second is a scalar times a vector so N[5] could be taken out of the sum (but I left it there to match the equation).
Final note: I see you're new to S.O. so I thought it would be helpful if I answered this question for you. In the future, please show some attempt at the code -- it really helps a lot.
I am creating a program that calculates the optimum angles to fire a projectile from a range of heights and a set initial velocity. Within the final equation I need to utilise, there is an inverse sec function present that is causing some troubles.
I have imported math and attempted to use asec(whatever) however it seems math can not calculate inverse sec functions? I also understand that sec(x) = 1/cos(x) but when I sub 1/cos(x) into the equation instead and algebraically solve for x it becomes a non real result :/.
The code I have is as follows:
print("This program calculates the optimum angles to launch a projectile from a given range of heights and a initial speed.")
x = input("Input file name containing list of heights (m): ")
f = open(x, "r")
for line in f:
heights = line
print("the heights you have selected are : ", heights)
f.close()
speed = float(input("Input your initial speed (m/s): "))
print("The initial speed you have selected is : ", speed)
ran0 = speed*speed/9.8
print(ran0)
f = open(x, "r")
for line in f:
heights = (line)
import math
angle = (math.asec(1+(ran0/float(heights))))/2
print(angle)
f.close()
So my main question is, is there any way to find the inverse sec of anything in python without installing and importing something else?
I realise this may be more of a math based problem than a coding problem however any help is appreciated :).
Let's say we're looking for real number x whose arcsecant is angle θ. Then we have:
θ = arcsec(x)
sec(θ) = x
1 / cos(θ) = x
cos(θ) = 1 / x
θ = arccos(1/x)
So with this reasoning, you can write your arcsecant function as:
from math import acos
def asec(x):
return acos(1/x)
"I also understand that sec(x) = 1/cos(x) but when I sub 1/cos(x) ..." Do you have to use sec or asec ?
Because sec(x)= 1/cos(x) and asec(x) = acos(1/x). Be careful the notation ^-1 is ambiguous, cos^-1(x) = acos(x) is different of [cos(x)]^-1.
angle = (math.asec(1+(ran0/float(heights))))/2
asec is not defined from -1 to 1
If you have a height lower than zero, and so the result of (ran0/float(heights)) is between -2 and 0, your angle will be non real.
I don't really know if this is what you asked for, but I hope it helps.
If math is OK for you to import, then you can use:
import math
def asec(x):
if x == 0:
return 1j * math.inf
else:
return math.acos(1 / x)
For some other ways of of re-writing asec(x), feast your eyes on the relevant Wikipedia article.
Alternatively, you could use Taylor series expansions, which always come in polynomial form, so, although that is only an approximation in a neighborhood of a given point, it would not require math.
For asec(x), its Taylor expansion in a neighborhood of ±∞ (also known as Laurent series) is given by (without using math):
def asec_taylor(x, pi=3.14159265):
if x == 0:
return 1j * float('inf')
else:
return pi / 2 - 1 / x - 1 / (6 * x ** 3) - 3 / (40 * x ** 5)
You can quickly check that the farther you are from 0, the better the approximation holds:
for x in range(-10, 10):
print(x, asec(x), asec_taylor(x))
-10 1.6709637479564565 1.670963741666667
-9 1.6821373411358604 1.6821373299281108
-8 1.696124157962962 1.6961241346516926
-7 1.714143895700262 1.7141438389326868
-6 1.7382444060145859 1.7382442416666668
-5 1.7721542475852274 1.7721536583333335
-4 1.8234765819369754 1.823473733854167
-3 1.9106332362490186 1.910611139814815
-2 2.0943951023931957 2.0939734083333335
-1 3.141592653589793 2.8124629916666666
0 (nan+infj) (nan+infj)
1 0 0.32912965833333346
2 1.0471975511965979 1.0476192416666668
3 1.2309594173407747 1.2309815101851853
4 1.318116071652818 1.3181189161458333
5 1.369438406004566 1.3694389916666667
6 1.4033482475752073 1.4033484083333334
7 1.4274487578895312 1.4274488110673134
8 1.4454684956268313 1.4454685153483076
9 1.4594553124539327 1.4594553200718894
If you can try of inverse of sec then it will be same as
>>>from mpmath import *
>>> asec(-1)
mpf('3.1415926535897931')
Here are the link in where you can better understand - [http://omz-software.com/pythonista/sympy/modules/mpmath/functions/trigonometric.html]
I am learning the Python tutorial on MIT, and I'm having a problem with one of the exercises. The exercise is,
Use the IPython prompt to calculate:
Positive root of the following equation: 34x2 + 68x - 510 = 0 Recall:
given ax2 + bx + c = 0 , then x = (-b +sqrt(b*b - 4ac))/(2*a)
I have entered
(-68)+(math.sqrt((68**2)-(4*34*510)))
in the iprompt, and I'm getting
Traceback (most recent call last):
File "", line 1, in
(-68)+(math.sqrt((68**2)-(434510)))
ValueError: math domain error
On calculating individually, I found that the value inside the square root is negative. Should I be adding some additional functions to enable negative root calculation, or is there something else that is wrong with my statement?
Can someone help me out?
Note: The solutions on the course page suggest making
(b**2-4ac)
positive before calculating the root. Will this not be mathematically inaccurate?
I am taking the same course, I did this way and got the right answers. Write the equation like this:
(-68+((68**2)-4*34*(-510))**0.5)/(2*34)
That will give you the 1st solution, just change the sign of plus to minus and you get the 2nd solution, as:
(-68-((68**2)-4*34*(-510))**0.5)/(2*34)
Check the photo I have attached, it is a screenshot of the solutions.
Screenshot of Spyder solving equation 34x^2+68x-510
Let f(x) = ax² + bx + c. If you want to solve f(x) = 0 in the field of real numbers, then you need to take care of the discriminant of f defined to be b² - 4ac. If the latter is negative, you do not have real solutions (and to have solutions you need to consider f as a complex polynomial, meaning that you want to find a solution to f(x) = 0 in the field of complex numbers).
Now, for your problem, it appears that you have a sign problem. The coefficient c is equal to -510 and not 510. Thus, 68² - 4*34*510 should be 68² - 4*34*(-510) = 68² + 4 * 34 * 510.
if f(x) = ax^2 + bx + c then its positive root will be
( -b + sqrt (b^2 - 4ac)) / 2a
According to your Question f(x) = 34x^2 + 68x - 510 = 0
So +ve root will be => ( -68 + sqrt (68^2 - 4*34*(-510)) ) / (2*34) = 3
In python code will be like -
from math import sqrt
print((-68 + sqrt(68**2 - 4*34*(-510)))/(2*34))
But what you did wrong is, you have taken co-efficient of 'C' is 510.
Instead It should be (-510).
I'm doing the course as well.
The question is from "getting started", so it shouldn't be hard.
And it should be related to the course material.
Therefore, here is what I have:
IDLE 1.2.4
>>> import math
>>> a=34
>>> b=68
>>> c=-510
>>> d = ( -b + math.sqrt ( b*b - 4*a*c))/(2 * a)
>>> print d
3.0
I get this error when using a python script that calculates pi using the Gauss-Legendre algorithm. You can only use up to 1024 iterations before getting this:
C:\Users\myUsernameHere>python Desktop/piWriter.py
End iteration: 1025
Traceback (most recent call last):
File "Desktop/piWriter.py", line 15, in <module>
vars()['t' + str(sub)] = vars()['t' + str(i)] - vars()['p' + str(i)] * math.
pow((vars()['a' + str(i)] - vars()['a' + str(sub)]), 2)
OverflowError: long int too large to convert to float
Here is my code:
import math
a0 = 1
b0 = 1/math.sqrt(2)
t0 = .25
p0 = 1
finalIter = input('End iteration: ')
finalIter = int(finalIter)
for i in range(0, finalIter):
sub = i + 1
vars()['a' + str(sub)] = (vars()['a' + str(i)] + vars()['b' + str(i)])/ 2
vars()['b' + str(sub)] = math.sqrt((vars()['a' + str(i)] * vars()['b' + str(i)]))
vars()['t' + str(sub)] = vars()['t' + str(i)] - vars()['p' + str(i)] * math.pow((vars()['a' + str(i)] - vars()['a' + str(sub)]), 2)
vars()['p' + str(sub)] = 2 * vars()['p' + str(i)]
n = i
pi = math.pow((vars()['a' + str(n)] + vars()['b' + str(n)]), 2) / (4 * vars()['t' + str(n)])
print(pi)
Ideally, I want to be able to plug in a very large number as the iteration value and come back a while later to see the result.
Any help appreciated!
Thanks!
Floats can only represent numbers up to sys.float_info.max, or 1.7976931348623157e+308. Once you have an int with more than 308 digits (or so), you are stuck. Your iteration fails when p1024 has 309 digits:
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216L
You'll have to find a different algorithm for pi, one that doesn't require such large values.
Actually, you'll have to be careful with floats all around, since they are only approximations. If you modify your program to print the successive approximations of pi, it looks like this:
2.914213562373094923430016933707520365715026855468750000000000
3.140579250522168575088244324433617293834686279296875000000000
3.141592646213542838751209274050779640674591064453125000000000
3.141592653589794004176383168669417500495910644531250000000000
3.141592653589794004176383168669417500495910644531250000000000
3.141592653589794004176383168669417500495910644531250000000000
3.141592653589794004176383168669417500495910644531250000000000
In other words, after only 4 iterations, your approximation has stopped getting better. This is due to inaccuracies in the floats you are using, perhaps starting with 1/math.sqrt(2). Computing many digits of pi requires a very careful understanding of the numeric representation.
As noted in previous answer, the float type has an upper bound on number size. In typical implementations, sys.float_info.max is 1.7976931348623157e+308, which reflects the use of 10 bits plus sign for the exponent field in a 64-bit floating point number. (Note that 1024*math.log(2)/math.log(10) is about 308.2547155599.)
You can add another half dozen decades to the exponent size by using the Decimal number type. Here is an example (snipped from an ipython interpreter session):
In [48]: import decimal, math
In [49]: g=decimal.Decimal('1e12345')
In [50]: g.sqrt()
Out[50]: Decimal('3.162277660168379331998893544E+6172')
In [51]: math.sqrt(g)
Out[51]: inf
This illustrates that decimal's sqrt() function performs correctly with larger numbers than does math.sqrt().
As noted above, getting lots of digits is going to be tricky, but looking at all those vars hurts my eyes. So here's a version of your code after (1) replacing your use of vars with dictionaries, and (2) using ** instead of the math functions:
a, b, t, p = {}, {}, {}, {}
a[0] = 1
b[0] = 2**-0.5
t[0] = 0.25
p[0] = 1
finalIter = 4
for i in range(finalIter):
sub = i + 1
a[sub] = (a[i] + b[i]) / 2
b[sub] = (a[i] * b[i])**0.5
t[sub] = t[i] - p[i] * (a[i] - a[sub])**2
p[sub] = 2 * p[i]
n = i
pi_approx = (a[n] + b[n])**2 / (4 * t[n])
Instead of playing games with vars, I've used dictionaries to store the values (the link there is to the official Python tutorial) which makes your code much more readable. You can probably even see an optimization or two now.
As noted in the comments, you really don't need to store all the values, only the last, but I think it's more important that you see how to do things without dynamically creating variables. Instead of a dict, you could also have simply appended the values to a list, but lists are always zero-indexed and you can't easily "skip ahead" and set values at arbitrary indices. That can occasionally be confusing when working with algorithms, so let's start simple.
Anyway, the above gives me
>>> print(pi_approx)
3.141592653589794
>>> print(pi_approx-math.pi)
8.881784197001252e-16
A simple solution is to install and use the arbitrary-precisionmpmath module which now supports Python 3. However, since I completely agree with DSM that your use ofvars()to create variables on the fly is an undesirable way to implement the algorithm, I've based my answer on his rewrite of your code and [trivially] modified it to make use ofmpmath to do the calculations.
If you insist on usingvars(), you could probably do something similar -- although I suspect it might be more difficult and the result would definitely harder to read, understand, and modify.
from mpmath import mpf # arbitrary-precision float type
a, b, t, p = {}, {}, {}, {}
a[0] = mpf(1)
b[0] = mpf(2**-0.5)
t[0] = mpf(0.25)
p[0] = mpf(1)
finalIter = 10000
for i in range(finalIter):
sub = i + 1
a[sub] = (a[i] + b[i]) / 2
b[sub] = (a[i] * b[i])**0.5
t[sub] = t[i] - p[i] * (a[i] - a[sub])**2
p[sub] = 2 * p[i]
n = i
pi_approx = (a[n] + b[n])**2 / (4 * t[n])
print(pi_approx) # 3.14159265358979