def trapz(fun, a, b, tol=1e-4, *args, **kwargs):
"""
Compute the area under the curve defined by
y = fun(x), for x between a and b
:param fun: the function to evaluate
:type fun: a function that takes teh vule to be integrated over as
its first argument. Any arguments can be passed in at the end.
:param a: the start point for the integration
:type a: a numeric value
:param b: the end point for the integration
:type b: a numeric value
:param tol=1e-4: accuracy expected.
any other arguments will be passed through to fun.
"""
# compute the range
# loop to try varying step sizes until desired accuracey is achieved
prev_s = None
n = 2 # start with only two steps
while True: # break out when desired accuracy is reached
vals = frange(a, b, n)
s = sum([fun(x, *args, **kwargs) for x in vals[1:-1]])
s += (fun(a, *args, **kwargs) + fun(b, *args, **kwargs)) / 2
s *= (b-a) / n
if prev_s is not None:
# check if we're close enough
# abs_tol is for comparison to zero
if isclose(s, prev_s, rel_tol=tol, abs_tol=tol):
return s
n *= 2
prev_s = s
# this could be a more sophisticated criterion
if n >= 2**22: # it's not going to work (about half the precision of a double)
raise ValueError("Solution didn't converge")
评论列表
文章目录