Why lambdify never stops? - python

x = symbols('x')
ch = 'exp(cos(cos(exp((sin(-0.06792841536110628))**(-6.045461643745118)))))'
f = lambdify(x, ch, "numpy")
print(float(f(2)))
It does not work, the programm is running and never ends(no error is issued).
My goal is to avoid this kind of cases (among multiple cases) by doing a try/except but i can't as there is no error
Why no error is released?
How can i avoid these cases ?
Thanks for your helping me !

In general, I'm not sure you can. SymPy or NumPy will keep trying to compute the number until precision is exhausted. But you can create a function that will raise and error if numbers are out of bounds for your interest:
>>> from sympy import cos as _cos, I, exp
>>> def cos(x):
... if abs(x) > 10**20: raise ValueError
... return _cos(x)
>>> exp(cos(cos(exp(5*(1+I)))))
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 2, in cos
ValueError
>>> f = lambda x: exp(cos(cos(exp(x))))
>>> f(sin(-0.06792841536110628)**-6.045461643745118)
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 1, in <lambda>
File "<string>", line 2, in cos
ValueError
But you have to think carefully about when you want to raise such an error. For example, SymPy has no trouble computing f(100) or f(100*I) if the non-error-catching cos is used. So think about when actually you want the error to rise.

lambdify is a lexical translator, converting a sympy expression to a python/numpy function.
Make a string with a symbol:
In [27]: ch = 'exp(cos(cos(exp((sin(x))**(-6.045461643745118)))))'
sympify(ch) has no problem, because it doesn't need to do any numeric calculation. So lambdify also works:
In [28]: f=lambdify(x,ch)
In [29]: f?
Signature: f(x)
Docstring:
Created with lambdify. Signature:
func(x)
Expression:
exp(cos(cos(exp((sin(x))**(-6.045461643745118)))))
Source code:
def _lambdifygenerated(x):
return (exp(cos(cos(exp(sin(x)**(-6.045461643745118))))))
The equivalent mpmath:
def _lambdifygenerated(x):
return (exp(cos(cos(exp(sin(x)**(mpf((1, 54452677612106279, -53, 56))))))))
And a working numeric evaluation:
In [33]: f(0j)
Out[33]: mpc(real='nan', imag='0.0')

Related

how do I solve the overflow error : math range error

I am getting an overflow error
import numpy as np
pi = np.pi
from scipy.integrate import quad
from math import exp
hbar = 1.055e-34
boltz = 1.381e-23
c = 2.998e8
def z(x):
return (x**3)/(exp(x)-1)
B=quad(z,0,np.inf)
A= ((boltz**4)*B)/(4*(pi**2)*(c**2)*(hbar**3))
print (A)
It is giving me an overflow error in line 11, i.e return (x**3)/(exp(x)-1)
You're hitting machine precision and python is freaking out.
>>> def z(x):
... return (x**3)/(exp(x)-1)
...
>>> z(709)
4.336616682334302e-300
>>> z(710)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in z
OverflowError: math range error
Just integrate up to ~700 and you'll be fine.
You can use np.exp instead of math.exp: it will raise a Warning for large numbers and return np.inf (which results in 1/np.inf = 0), instead of raising an OverFlowError
def z(x):
return (x**3)/(np.exp(x)-1) #replace math.exp by np.exp
B, err =quad(z,0,np.inf) # add the err, or use B=quad(...)[0] as quad will also return the integration error
A= ((boltz**4)*B)/(4*(pi**2)*(c**2)*(hbar**3))
print(A)
>> 5.668949306250541e-08

How does the `j` suffix for complex numbers work? Can I make my own suffix?

I know what are complex numbers and how they mathematically work, but how is it done for python to know it's complex just by putting a j after a digit ?
>>> j
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'j' is not defined
>>> 1*j
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'j' is not defined
>>> 1j
1j
>>> 1j**2
(-1+0j)
Can I make my own suffix, let's say p (for strictly positive) ?
Could I do something working like this ?
>>> ... some weird stuff here ...
>>> p
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'p' is not defined
>>> 1*p
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'p' is not defined
>>> -1p
1p
>>> 0p
1p
>>>
This is built into Python's grammar, just like the decimal point is, or the e in scientific notation (1e10 etc.). The j makes a numeric literal imaginary.
Python does not allow you to change this. That doesn't mean you can't--you could amend the grammar--but then the language is no longer Python.
The closest approximation allowed in Python would be by implementing an operator.
>>> class StrictlyPositive:
def __rmatmul__(self, number):
return abs(number)
>>> p = StrictlyPositive()
>>> -1#p
1
But you have to be careful of operator precedence when doing stuff like this. Why not just use the builtin abs directly?

f = lambda n:(1,f(n-1)*n)[n>1] gives RunTimeError in Python 3

I'm golfing a factorial function in Python 3, but my lambda doesn't work:
f = lambda n:(1,f(n-1)*n)[n>1]
It raises this error:
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 1, in <lambda>
# Many other identical lines...
RuntimeError: maximum recursion depth exceeded
Where's the problem?
Tuples aren't lazily evaluated. Even though f(0) will select the first element in the tuple (1, f(-1)*0), it still has to call f(-1) before it can do so. And before f(-1) can return, it has to call f(-2), and so on forever.
Consider using the inline conditional instead, which does delay evaluation until it knows which branch it's going to go down.
f = lambda n:1 if n <= 1 else f(n-1)*n
print f(10)

Simple Function does not work, dont see the error

I am a beginning python programmer, but have written several scripts including ones in which I define my own functions and use them. I cannot seem to get any user defined functions to work within the IDLE. Wondering if I am crazy/dumb. Can somebody please explain the following results?Thanks:
def f(x,y):
solution = x+y
return solution
f(2,2)
SyntaxError: invalid syntax
>>> a = f(2,2)
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
a = f(2,2)
NameError: name 'f' is not defined
def g(x):
solution = x + 2
return solution
g(2)
SyntaxError: invalid syntax
>>> a = g(2)
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
a = g(2)
NameError: name 'g' is not defined
Add a blank line after the definition of the function to make the interpreter understand that it's finished.
>>> def f(x,y):
solution = x+y
return solution
>>> f(2,2)
4

How to fix this python program?

import math
def p(n):
return 393000*((288200/393000)^n * math.exp(-(288200/393000)))/math.factorial(n)
print p(3)
When I run it, I get the following error message:
Traceback (most recent call last):
File "poisson.py", line 6, in <module>
print p(3)
File "poisson.py", line 4, in p
return 393000*((288200/393000)^n * math.exp(-(288200/393000)))/math.factoria
l(n)
TypeError: unsupported operand type(s) for ^: 'int' and 'float'
Replace ^ with ** in
(288200/393000)^n
Bear in mind that
288200/393000
Returns 0
Maybe you should try using decimal numbers:
import math
def p(n):
a = 393000.0 # <-- notice the .0
b = 288200.0
c = b / a
return a * ( c**n * math.exp(-c) )/ math.factorial(n)
print p(3)
Returns:
12406.890756
Is the ^ supposed to mean exponentiation? If so, use ** instead.
You can also use math.pow:
>>> import math
>>> math.pow(3,2)
9.0
Though actually it looks like maybe this isn't the best idea, since math.pow is more for C extension compatibility, and doesn't handle all the cases that ** does:
>>> 2**3000
1230231922161117176931558813276752514640713895736833715766118029160058800614672948775360067838593459582429649254051804908512884180898236823585082482065348331234959350355845017413023320111360666922624728239756880416434478315693675013413090757208690376793296658810662941824493488451726505303712916005346747908623702673480919353936813105736620402352744776903840477883651100322409301983488363802930540482487909763484098253940728685132044408863734754271212592471778643949486688511721051561970432780747454823776808464180697103083861812184348565522740195796682622205511845512080552010310050255801589349645928001133745474220715013683413907542779063759833876101354235184245096670042160720629411581502371248008430447184842098610320580417992206662247328722122088513643683907670360209162653670641130936997002170500675501374723998766005827579300723253474890612250135171889174899079911291512399773872178519018229989376L
vs.
>>> import math
>>> math.pow(2, 3000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: math range error
see http://mail.python.org/pipermail/python-list/2003-November/236169.html for a little more detail
EDIT: In response to your question as to why it returns 0.0, that's because you are raising 0 to a power - you are using / for division, which by default is integer division and will truncate. use from __future__ import division to get floating point divison.

Categories