Last active
December 14, 2015 17:19
-
-
Save garyrh/5121714 to your computer and use it in GitHub Desktop.
Nootan, a monstrosity of a Newton method program.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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