Skip to content

Instantly share code, notes, and snippets.

@bru32
Last active August 13, 2025 00:22
Show Gist options
  • Save bru32/10349af42607ddd5c74308da9233b22c to your computer and use it in GitHub Desktop.
Save bru32/10349af42607ddd5c74308da9233b22c to your computer and use it in GitHub Desktop.
Interesting idea to write Newton's root finding method as a decorator
"""
Traditional Newton root finding method
and Alternative using decorators...
Author: Bruce Wernick
Date: 13 August 2025
"""
def newt(f, x, **kwargs):
maxits = kwargs.get("maxits", 48)
tol = kwargs.get("tol", 1e-6)
for its in range(maxits):
xo = x
fx, dfx = f(x)
x -= fx/dfx
if abs(fx) <= tol: return x
if abs(x-xo) <= tol*(abs(x)+1): return x
#print(f"{its:2d} {x:12.9f} {fx:12.9f}")
return x
f = lambda x: ((x-3)*(x+5), 2*(x+1))
x = newt(f, 2.5)
#print(f"root={x:0.9g}")
# ----------------------------------
# Write Newton method as a decorator
# ----------------------------------
def newton(**kwargs):
maxits = kwargs.get("maxits", 48)
tol = kwargs.get("tol", 1e-6)
def decorator(f):
def wrapper(x):
for its in range(maxits):
xo = x
fx, dfx = f(x)
x -= fx/dfx
if abs(fx) <= tol: return x
if abs(x-xo) <= tol*(1+abs(x)): return x
print(f"{its:2d} {x:12.9f} {fx:12.9f}")
return x
return wrapper
return decorator
@newton(tol=1e-12)
def f(x):
"""return f(x) and slope(x)"""
return ((x-3)*(x+5), 2*(x+1))
x = f(2.5)
#print(f"root={x:0.9g}")
@bru32
Copy link
Author

bru32 commented Aug 13, 2025

I'm not sure if this has any merit!
You can write a function like this...

def f(x):
  """return f(x) and slope(x)"""
  return ((x-3)*(x+5), 2*(x+1))

and then simply decorate it with...

@newton(tol=1e-12)

to find the root.

If there were other useful decorators, then it might be worthwhile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment