I wrote the following code, after printing about 10 outputs it gets error
return 1/sqrt(Om*(1+z)**3+omg0*(1+z)**6+(1-Om-omg0))
ValueError: math domain error
the three first functions are correct and work well in other programs please do not be sensitive about their structures, I think the problem is in for-loop and choosing some values which cannot satisfy the condition of sqrt. Could I add some lines to tell Python avoid numbers which lead to math domain error? If yes, How should I do that? I mean passing the step which leads to negative value under sqrt?
Cov is a 31*31 mtrix, xx[n] is a list of 31 numbers.
def ant(z,Om,w):
return 1/sqrt(Om*(1+z)**3+w*(1+z)**6+(1-Om-w))
def dl(n,Om,w,M):
q=quad(ant,0,xx[n],args=(Om,w))[0]
h=5*log10((1+xx[n])*q)
fn=(yy[n]-M-h)
return fn
def c(Om,w,M):
f_list = []
for i in range(31): # the value '2' reflects matrix size
f_list.append(dl(i,Om,w,M))
A=[f_list]
B=[[f] for f in f_list]
C=np.dot(A,Cov)
D=np.dot(C,B)
F=np.linalg.det(D)*0.000001
return F
N=100
for i in range (1,N):
R3=np.random.uniform(0,1)
Omn[i]=Omo[i-1]+0.05*np.random.normal()
wn[i]=wo[i-1]+0.05*np.random.normal()
Mn[i]=Mo[i-1]+0.1*np.random.normal()
L=exp(-0.5*(c(Omn[i],wn[i],Mn[i])-c(Omo[i-1],wo[i-1],Mo[i-1])))
if L>R3:
wo[i]=wn[i]
else:
wo[i]=wo[i-1]
print(wo[i])
The output is:
0.12059556415714912
0.16292726528216397
0.16644447885609648
0.1067588804671105
0.0321446951572128
0.0321446951572128
0.013169965429457382
Traceback (most recent call last):
......
return 1/sqrt(Om*(1+z)**3+omg0*(1+z)**6+(1-Om-omg0))
ValueError: math domain error
Here are some options:
Replace sqrt(...) with (...)**0.5. This will produce complex numbers, which may or may not be acceptable. For example (-1)**0.5 produces i which in Python will appear as 1j (ignoring floating point errors).
Catch errors and move on. Since you probably want to catch the errors higher up, I recommend translating the ValueError from sqrt into a custom error:
class SqrtError(ValueError):
pass
def ant(z, Om, w):
val = Om * (1 + z) ** 3 + w * (1 + z) ** 6 + (1 - Om - w)
try:
sq = sqrt(val)
except ValueError:
raise SqrtError
return 1 / sq
Then it sounds like you want to keep trying new random numbers until you get one that works, which could be done like so:
for i in range(1, N):
R3 = np.random.uniform(0, 1)
while True:
Omn[i] = Omo[i - 1] + 0.05 * np.random.normal()
wn[i] = wo[i - 1] + 0.05 * np.random.normal()
Mn[i] = Mo[i - 1] + 0.1 * np.random.normal()
try:
L = exp(-0.5 * (c(Omn[i], wn[i], Mn[i]) - c(Omo[i - 1], wo[i - 1], Mo[i - 1])))
except SqrtError:
continue
else:
break
if L > R3:
wo[i] = wn[i]
else:
wo[i] = wo[i - 1]
Your code is trying to find the square root of a negative number.
This is not allowed with real-valued numbers (for obvious mathematical reasons), so your best bet is to use a try/except block:
def ant(z,Om,w):
try:
return 1/sqrt(Om*(1+z)**3+omg0*(1+z)**6+(1-Om-omg0))
except ValueError:
return None
Related
For some reason it shows an error message: TypeError: argument should be a string or a Rational instance
import cmath
from fractions import Fraction
#Function
# Quadratic equatrion solver
def solver(a_entry, b_entry, c_entry):
a = int(a_entry)
b = int(b_entry)
c = int(c_entry)
d = (b*b) - (4*a*c)
sol1 = (-b-cmath.sqrt(d)/(2*a))
sol2 = (-b+cmath.sqrt(d)/(2*a))
sol3 = Fraction(sol1)
sol4 = Fraction(sol2)
print(f"Value of x1 = {sol3} and value of x2 = {sol4}")
solver(1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in solver
File "/usr/lib/python3.10/fractions.py", line 139, in __new__
raise TypeError("argument should be a string "
TypeError: argument should be a string or a Rational instance
I am a new programmer and I saw that this code generates a weird number (example: 5.42043240824+0j {inaccurate values})
when i give random values. So I want it to give either an accurate decimal values or in fraction. The fraction method dosen't work for some reason. Can someone please help. Alot of thanks.
2 things wrong in your code :
Use math instead of cmath as cmath is used for complexed values (it will always returns a complexe value, even 1+0j) which is not compatible with Fraction.
Be careful you wrote : (-b-cmath.sqrt(d)/(2*a)) but is should be ((-b-cmath.sqrt(d))/(2*a))
Also, the solution might no exist. For example, resolving 1x^2 + 3x + 10 has no answer (your fonction does not cross x axe). It still has complexe answer(s).
To avoid this you can use a try except to catch errors. OR you can validate that d^2 is greater than 4ac because you can't sqrt negative values (except with complexe values ;) ) :
def solver():
a = int(entry.get())
b = int(entry1.get())
c = int(entry2.get())
d = (b*b) - (4*a*c)
if d < 0:
text = "no real answer ! The function doesn't cross X axe !"
label2.configure(text = text)
else:
sol1 = ((-b-math.sqrt(d))/(2*a))
sol2 = ((-b+math.sqrt(d))/(2*a))
sol3 = Fraction(sol1)
sol4 = Fraction(sol2)
label2.configure(text = f"Value of x1 = {sol3} and value of x2 = {sol4}")
Hope it helps
The issue with sqrt
It appears that you do not want to evaluate the square roots to numerical approximations. But that is exactly what cmath.sqrt and math.sqrt do: they calculate numerical approximations of square roots.
For instance:
import math
print( math.sqrt(2) )
# 1.4142135623730951
If you are not interested in numerical approximations, then I suggest using a library for symbolic calculus. The best-known library for symbolic calculus in python is called sympy. This module has a sympy.sqrt function that will simplify a square root as much as it can, but without returning a numerical approximation:
import sympy
print( sympy.sqrt(9) )
# 3
print( sympy.sqrt(2) )
# sqrt(2)
print( sympy.sqrt(18) )
# 3*sqrt(2)
More information about sympy: https://docs.sympy.org/latest/tutorials/intro-tutorial/intro.html
Other advice
When you write a program, it is most usually a good idea to cleanly separate the parts of the code that deal with algorithms, maths, and logic, from the parts of the code that deal with input and output. I suggest writing two functions, one that solves quadratic equations, and one that does input and output:
import sympy
# returns solutions of a x**2 + b x + c == 0
def solver(a, b, c):
Delta = b*b - 4*a*c
sol1 = (-b - sympy.sqrt(Delta)) / (2*a)
sol2 = (-b + sympy.sqrt(Delta)) / (2*a)
return (sol1, sol2)
# ask for user input and solve an equation
def input_equation_output_solution():
a = int(entry.get())
b = int(entry1.get())
c = int(entry2.get())
sol1, sol2 = solver(a, b, c)
label2.configure(text = f"Value of x1 = {sol1} and value of x2 = {sol2}")
I want to replace the divisor with a very small number if it equals to 0. I am doing an operation which is like:
A = pow(X,2)/(q - P)
It computes these values and stores them in an array (for looped). However, at certain places q - P = 0, which throws a runtime error. I know that there is a work around, I do not want that. How can I set q - P to a very small number in case q - P = 0 for a particular iteration.
I would recommend to use a try except block and set A to a different value if a ZeroDivisionError error occurs:
try:
A = (pow(X,2))/(q - P))
except ZeroDivisionError:
A = 99999999999 #big nuber because devision by a small number
# you can also set A to infinity with `A = np.inf`
If thats not an option for you (e.g. you really want to change q or P and not only A) you can simply add a small number to q or P
if q == P:
q+= 0.00000000000001 # or P+=small_number or q-=small_number or P-=small_number
You can use an inline if:
very_small_number = 0.001
A = pow(X, 2) / ( q - P if q != P else very_small_number )
You can use the following trick:
diff = q - P or .001
A = pow(X, 2) / diff
or
A = pow(X, 2) / (q - P or .001)
So, I'm trying to find the value of cos(x), where x=1.2. I feel the script I have written should be fine, however, the value I get out isn't correct. That is; cos(1.2)=0.6988057880877979, for 25 terms, when I should get out: cos(1.2)=0.36235775.
I have created a similar program for calculating sin(1.2) which works fine.
Calculating sin(1.2):
import math as m
x=1.2
k=1
N=25
s=x
sign=1.0
while k<N:
sign=-sign
k=k+2
term=sign*x**k/m.factorial(k)
s=s+term
print('sin(%g) = %g (approximation with %d terms)' % (x,s,N))
Now trying to calculate cos(1.2):
import math as m
x=1.2
k=1
N=25
s=x
sign=1.0
while k<N:
sign=-sign
k=k+1
term=sign*x**k/m.factorial(k)
s=s+term
print(s)
You shouldn't be setting your initial sum to 1.2, and your representation of the expansion
is a bit off - we need to account for the even-ness of the function, so increment k by 2. Also, without modifying your program structure, you'd have to set the initial variables so they are correctly put to their starting values at the beginning of the first loop. Re-ordering your loop control flow a bit, we have
import math as m
x=1.2
k=0
N=25
s=0
sign=1.0
while k<N:
term=sign*x**(k)/m.factorial(k)
s=s+term
k += 2
sign = -sign
print(s)
Gives
0.3623577544766735
I think you're using the wrong series for the cosine, the correct formula would be (I highlighted the important differences with ^):
sum_over_n [(-1)**n * x ** (2 * n) / (math.factorial(2 * n))]
# ^^^^ ^^^^
that means to add n-terms you have something like:
def cosine_by_series(x, terms):
cos = 0
for n in range(terms):
cos += ((-1)**n) * (x ** (2*n)) / (math.factorial(2 * n))
return cos
# or simply:
# return sum(((-1)**n) * (x ** (2*n)) / (math.factorial(2 * n)) for n in range(terms)
which gives:
>>> cosine_by_series(1.2, 30)
0.3623577544766735
I understand there is a erf (Wikipedia) function in python. But in this assignment we are specifically asked to write the error function as if it was not already implemented in python while using a while loop.
erf (x) is simplified already as : (2/ (sqrt(pi)) (x - x^3/3 + x^5/10 - x^7/42...)
Terms in the series must be added until the absolute total is less than 10^-20.
First of all - SO is not the place when people code for you, here people help you to solve particular problem not the whole task
Any way:
It's not too hard to implement wikipedia algorithm:
import math
def erf(x):
n = 1
res = 0
res1 = (2 / math.sqrt(math.pi)) * x
diff = 1
s = x
while diff > math.pow(10, -20):
dividend = math.pow((-1), n) * math.pow(x, 2 * n + 1)
divider = math.factorial(n) * (2 * n + 1)
s += dividend / divider
res = ((2 / math.sqrt(math.pi)) * s)
diff = abs(res1 - res)
res1 = res
n += 1
return res
print(erf(1))
Please read the source code carefully and post all questions that you don't understand.
Also you may check python sources and see how erf is implemented
I have to write a function, s(x) = x * sin(3/x) in python that is capable of taking single values or vectors/arrays, but I'm having a little trouble handling the cases when x is zero (or has an element that's zero). This is what I have so far:
def s(x):
result = zeros(size(x))
for a in range(0,size(x)):
if (x[a] == 0):
result[a] = 0
else:
result[a] = float(x[a] * sin(3.0/x[a]))
return result
Which...doesn't work for x = 0. And it's kinda messy. Even worse, I'm unable to use sympy's integrate function on it, or use it in my own simpson/trapezoidal rule code. Any ideas?
When I use integrate() on this function, I get the following error message: "Symbol" object does not support indexing.
This takes about 30 seconds per integrate call:
import sympy as sp
x = sp.Symbol('x')
int2 = sp.integrate(x*sp.sin(3./x),(x,0.000001,2)).evalf(8)
print int2
int1 = sp.integrate(x*sp.sin(3./x),(x,0,2)).evalf(8)
print int1
The results are:
1.0996940
-4.5*Si(zoo) + 8.1682775
Clearly you want to start the integration from a small positive number to avoid the problem at x = 0.
You can also assign x*sin(3./x) to a variable, e.g.:
s = x*sin(3./x)
int1 = sp.integrate(s, (x, 0.00001, 2))
My original answer using scipy to compute the integral:
import scipy.integrate
import math
def s(x):
if abs(x) < 0.00001:
return 0
else:
return x*math.sin(3.0/x)
s_exact = scipy.integrate.quad(s, 0, 2)
print s_exact
See the scipy docs for more integration options.
If you want to use SymPy's integrate, you need a symbolic function. A wrong value at a point doesn't really matter for integration (at least mathematically), so you shouldn't worry about it.
It seems there is a bug in SymPy that gives an answer in terms of zoo at 0, because it isn't using limit correctly. You'll need to compute the limits manually. For example, the integral from 0 to 1:
In [14]: res = integrate(x*sin(3/x), x)
In [15]: ans = limit(res, x, 1) - limit(res, x, 0)
In [16]: ans
Out[16]:
9⋅π 3⋅cos(3) sin(3) 9⋅Si(3)
- ─── + ──────── + ────── + ───────
4 2 2 2
In [17]: ans.evalf()
Out[17]: -0.164075835450162