I am testing a function to find the root of a mathematical function in Python and if there is no root on the interval, a RecursionError
is raised. However, when I try to handle the exception with a try-except block, it isn't raised anymore. What am I missing?
import math
sgn = lambda x: math.copysign(1, x)
def bisect(f, a, b, eps=1e-6):
"""
Find an approximate root of f in the interval [a, b].
Parameters
----------
f : function
A mathematical function, defined and with root on [a, b]
a, b : numbers
Endpoints of the interval. a < b.
eps : number, optional, default 1e-6
Tolerance of error.
Returns
-------
x : number
Approximate root of f on [a, b]
"""
if a > b:
raise ValueError("`b` needs to be greater than `a` for the interval [a, b] to exist.")
x = (a + b) / 2
if abs(f(x)) < eps:
return x
try:
if sgn(f(a)) != sgn(f(x)):
return bisect(f, a, x, eps)
else:
return bisect(f, x, b, eps)
except RecursionError as e:
raise RecursionError(f"There seems to be no root of f on the interval [{a}, {b}]")
def test_bisect():
"""Verify `bisect` using `f` = cos(pi * x), `a` = 0 `b` = 0.82 and `eps` = 1e-12."""
from math import cos, pi
f = lambda x: cos(pi * x)
a = 0
b = 0.4
eps = 1e-12
expected = 0.5
computed = bisect(f, a, b, eps)
error = abs(expected - computed)
tolerance = 1e-12
success = error < tolerance
msg = f"""
Error testing `piecewise`.
Expected: {expected}
Computed: {computed}
Error: {error:13.6e}
Tolerance: {tolerance:13.6e}"""
assert success, msg
test_bisect()
I think you had the try/except
in the wrong place. I moved it to inside the test_bisect()
function.
import math
sgn = lambda x: math.copysign(1, x)
def bisect(f, a, b, eps=1e-6):
"""
Find an approximate root of f in the interval [a, b].
Parameters
----------
f : function
A mathematical function, defined and with root on [a, b]
a, b : numbers
Endpoints of the interval. a < b.
eps : number, optional, default 1e-6
Tolerance of error.
Returns
-------
x : number
Approximate root of f on [a, b]
"""
if a > b:
raise ValueError("`b` needs to be greater than `a` for the interval [a, b] to exist.")
x = (a + b) / 2
if abs(f(x)) < eps:
return x
if sgn(f(a)) != sgn(f(x)):
return bisect(f, a, x, eps)
else:
return bisect(f, x, b, eps)
def test_bisect():
"""Verify `bisect` using `f` = cos(pi * x), `a` = 0 `b` = 0.82 and `eps` = 1e-12."""
from math import sin, pi, cos
f = lambda x: cos(pi * x)
a = 0
b = 0.4
eps = 1e-12
expected = 0.5
try:
computed = bisect(f, a, b, eps)
except RecursionError as e:
print(f"There seems to be no root of f on the interval [{a}, {b}]")
return
error = abs(expected - computed)
tolerance = 1e-12
success = error < tolerance
msg = f"""
Error testing `piecewise`.
Expected: {expected}
Computed: {computed}
Error: {error:13.6e}
Tolerance: {tolerance:13.6e}"""
assert success, msg
test_bisect()
I found the problem.. It seems the exception is not raised when using a Jupyter Notebook. I mean it is raised without the try-except block, but with it, it only works from the command line.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.