Skip to content

Instantly share code, notes, and snippets.

@garyrh
Last active December 14, 2015 17:19
Show Gist options
  • Save garyrh/5121714 to your computer and use it in GitHub Desktop.
Save garyrh/5121714 to your computer and use it in GitHub Desktop.
Nootan, a monstrosity of a Newton method program.
#!/usr/bin/env python2.7
'''
Nootan, a monstrosity of a Newton method program.
Rules:
Use on polynomials. Examples:
x^2
2x^3+8x^2-9x+9
-3x^{5}-6x^{4}+7x^{3}-5x^{2}+4
Don't do things like this:
(x^2)^5 # Perish the thought!
x**6+9x^2
x^2*8
(No asterisks!)
(No parens!)
(No functions!)
Square roots must be expressed as floats, i.e. x^.5
is the square root of x.
Date: 08/March/2013
By: Gary Herreman
'''
import math
import re
def getInput():
''' Returns equation and x0 input
'''
eq = raw_input("Equation? ")
x0 = raw_input("x0? ")
return eq.replace(" ", ""),int(x0)
def equation(eq, x):
return eval(eq)
def derivative(d, x):
return eval(d)
def calcDerivative(eq):
''' Does just what you'd think. Given string eq, a polynomial,
it uses simple substitution using the power rule to calculate
the derivative and returns it as a string.
'''
posList = []
derivList = []
# Separate negative terms from each positive term
for term in eq.split("+"):
posList.append(term.split("-")[0])
if "-" in term:
for num in xrange(1,len(term.split("-"))):
posList.append("{0}{1}".format("-",term.split("-")[num]))
for term in posList:
if "^" in term: # Power rule
nterm = term.split("x^")
if len(nterm) == 1 or nterm[0] == "": # No coef?
coef = 1
elif nterm[0] == "-": # negative coef?
coef = -1
else:
coef = nterm[0]
exp = nterm[1]
newCoef = float(exp)*int(coef)
newExp = float(exp)-1
derivList.append("{0}x^{1}".format(newCoef, newExp))
elif "x" in term: # Term has x in it! Yay!
if term.split("x")[0] != '' and term != "-x":
derivList.append(term.split("x")[0])
elif term == "x": # d/dx x = 1
derivList.append("1")
elif term == "-x":
derivList.append("-1")
else:
derivList.append("0") # Constant rule
# Glue all terms together with addition
return '+'.join(derivList).replace("x", "*x").replace("^", "**")
def main(eq, x):
# Warning: Regex below!
# Remove pointy brackets from tex code
pattern = re.compile(r'(?:x\^\{)(?P<exp>\-*\d)(?:\})')
eq = pattern.sub("x^\g<exp>", eq)
d = calcDerivative(eq)
# Carets to ** for term ax^n and add * for term so that ax^n -> a*x**n
pattern = re.compile(r'(?P<coef>\d)(?:x)(?:\^)')
eq = pattern.sub("\g<coef>*x**", eq)
# Carets to ** for term (-|+|at the beginning)x^n
pattern = re.compile(r'(?P<coef>(\-|\+|^))(?!\d)(?:x)(?:\^)')
eq = pattern.sub("\g<coef>x**", eq)
# Add extra * for term so that ax -> a*x
pattern = re.compile(r'(?P<coef>\d+)(?:x)(?!\^)')
eq = pattern.sub("\g<coef>*x", eq)
counter = 1
print "Equation = {0}".format(eq)
print "Derivative = {0}".format(d)
print "x0 = {0}".format(x)
while 1:
yval = float(equation(eq, x))
yvalDeriv = float(derivative(d, x))
x = x - (yval/yvalDeriv)
print "\nx{0} = {1}".format(counter, x)
print "f(x) = {0}".format(yval)
print "d/dx f(x) = {0}".format(yvalDeriv)
inp = raw_input("Continue? ")
if inp == "n": quit()
counter += 1
if __name__=='__main__':
equ, x = getInput()
main(equ, x)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment