Search code examples
pythonpython-3.xscipysympynewtons-method

Newton-Raphson's method user input and numerical output problems


I've been trying to create a script that allows the user to input an equation and returned the root of that equation. However I've ran into an issue and I've noticed that on running the program it takes the input and runs it through the loop but it doesn't assign the variables to the functions.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.lines as lines
from matplotlib import style
from scipy.misc import derivative
import sympy as sp

symx = sp.Symbol('x')

def f(symx):
    tmp = sp.sympify(input("Input your function here: "))
    return tmp;

def fprime(symx):
    tmp = sp.diff(f(symx))
    return tmp;

def newtons_method(f, fprime, symx):   
    guess = int(input("Enter an initial guess: ")) # Convert to an int immediately.
    for i in range(1,10):
        nextGuess = guess - f(guess)/fprime(guess)
        print(nextGuess)
        guess = nextGuess

def main():
    newtons_method(f, fprime, symx)
if __name__ == "__main__":
    main()

This is what the script outputs;

Enter an initial guess: 2
Input your function here: 2*x**3 + 2*x**2
Input your function here: 2*x**3 + 2*x**2
2 - (2*x**3 + 2*x**2)/(6*x**2 + 4*x)
Input your function here: 2*x**3 + 2*x**2 
Input your function here: 2*x**3 + 2*x**2 
2 - 2*(2*x**3 + 2*x**2)/(6*x**2 + 4*x)

Any help on improving is greatly appreciated, but could you also explain in depth any mistakes and improvements thank you.


Solution

  • You should not call the input function at any time, just in the initial moment, besides it is not necessary to pass the names of the functions.

    import sympy as sp
    
    x = sp.symbols('x')
    
    def f(symx):
        tmp = sp.sympify(symx)
        return tmp
    
    def fprime(symx):
        tmp = sp.diff(f(symx))
        return tmp;
    
    def newtons_method():   
        guess = sp.sympify(float(input("Enter an initial guess: "))) # Convert to an int immediately.
        symx = input("Input your function here: ")
        div = f(symx)/fprime(symx)
    
        for i in range(1, 10):
            print(guess.evalf())
            nextGuess = guess - div.subs(x, guess)
            guess = nextGuess
    
    
    def main():
        newtons_method()
    if __name__ == "__main__":
        main()
    

    Test:

    Enter an initial guess: 2
    Input your function here: 2*x**3 + 2*x**2
    2.00000000000000
    1.25000000000000
    0.760869565217391
    0.448024718605164
    0.254024574811046
    0.138693453631666
    0.0733275286119194
    0.0378747932767810
    0.0192767426403216
    
    Enter an initial guess: 2
    Input your function here: x**2-2
    2.00000000000000
    1.50000000000000
    1.41666666666667
    1.41421568627451
    1.41421356237469
    1.41421356237310
    1.41421356237309
    1.41421356237310
    1.41421356237309