2
$\begingroup$

I'm trying to write a program for finding the root of f(x)=e^x+sin(x)-4 by Newton's Method but I'm instructed to not use the built in function and write the code from scratch. I'm pretty new to this and this is what I've come up with so far. I'm curious about what I need to fix to make it better/work.

f[x_]:= Exp[x]+Sin[x]-4 (* This is my starting function *)
g[x_]:= x-(f[x]/f'[x])  (* Formula for Newton's Method *)
count=0;
maxiterations=100; (* Max times function will run *)
TOL=10^(-8); (* Tolerance for stopping condition *)
xprevious=1.0; (* This is my initial guess *)

While[Abs[xcurrent-xprevious] >= TOL && count <= maxiterations,
 {count++, xcurrent=g[xcurrent]}]

(* While my current and previous guess are above my tolerance and I haven't gone over 
my max iterations program will continue to run, adding one to the count each time and
putting xcurrent into the Newton's Method Equation *)

Obviously I am having some troubles with this code. What do I need to do to fix it?

$\endgroup$
4
  • 2
    $\begingroup$ The first thing you need to do is read a few tutorials and at least get familiar with the basic syntax. Go to the documentation centre, click Common How-Tos at the bottom and read the first few. "f(x_)" is not a function in Mathematica. $\endgroup$
    – Szabolcs
    Commented Oct 6, 2015 at 19:32
  • $\begingroup$ functions use square brackets. Euler's e is written with a capital E. Built-in keywords always start with a capital (sin -> Sin) $\endgroup$ Commented Oct 6, 2015 at 19:35
  • $\begingroup$ Sorry I do know that I just typed it in wrong. $\endgroup$
    – J_Smith88
    Commented Oct 6, 2015 at 19:36
  • $\begingroup$ Related: (59877), (93957) $\endgroup$
    – Michael E2
    Commented Oct 7, 2015 at 0:16

2 Answers 2

2
$\begingroup$

For a beginner one hint:

f[x_] = Exp[x] + Sin[x] - 4 // N;
NestList[(# - f[#]/f'[#]) &, 1, 5]
{1, 1.1351, 1.12999, 1.12998, 1.12998, 1.12998}

Please read the documentation

$\endgroup$
6
  • $\begingroup$ Or NestWhileList[(# - f[#]/f'[#]) &, 1, TOL < Abs[#1 - #2] &, 2] $\endgroup$
    – march
    Commented Oct 6, 2015 at 19:40
  • $\begingroup$ @ march I said "one hint":) $\endgroup$
    – user31001
    Commented Oct 6, 2015 at 20:08
  • 2
    $\begingroup$ Or just FixedPointList[# - f[#]/f'[#] &, 1.] or FixedPoint[# - f[#]/f'[#] &, 1.] $\endgroup$
    – Bob Hanlon
    Commented Oct 6, 2015 at 20:09
  • $\begingroup$ Oh I see, I guess I gave away the answer you were hinting at. :) Oh, and @BobHanlon is piling on with more hints! $\endgroup$
    – march
    Commented Oct 6, 2015 at 20:11
  • 1
    $\begingroup$ @march life's a bitch! $\endgroup$
    – user31001
    Commented Oct 6, 2015 at 20:20
2
$\begingroup$

I think it is reasonable to try to produce correct and robust code that will apply Newton's algorithm for finding a zero of a differentiable function of one real variable while maintaining the OP's procedural style.

For robustness, a clear distinction will be made between arguments and localized ancillary variables. The arguments will be

  • f, the function for which a zero is sought
  • guess, the initial guess for the location of the root
  • maxiter, the maximum number of iteration to performed before giving up
  • tolerance, the distance between two iterates of the root that is considered good enough to terminate the solver. This will an optional argument with the default of 1.*^-8 as specified by the OP.

The solver uses Newton's formula to derive a pure function iterator from the function passed to it. That Mathematica can do this symbolically is a great advantage.

The solver will return $Failed if fails to converge after maxiter iterations.

solver[f : (_Function | _Symbol),
     guess_?NumericQ,
     maxiter_Integer /; maxiter > 0,
     tolerance : _?NumericQ : 1.*^-8] /; .1 > tolerance > 0. :=
   Module[{iter, count, xprevious, xcurrent},
     iter = (# - f[#]/f'[#] &);
     count = 0;
     xcurrent = guess;
     xprevious = guess + 2.;
     While[Abs[xcurrent - xprevious] >= tolerance && count <= maxiter,
       xcurrent = iter[xprevious = xcurrent];
       count++];
     If[count <= maxiter, xcurrent, $Failed]]

Let's see if the solver can solve the OP's example problem, i.e., finding a root near 1. for the function

f[x_] := Exp[x] + Sin[x] - 4

 With[{x = solver[f, 1., 5]}, {x, f[x]}]
{1.12998, 0.}

Here it finds $\sqrt{2}$

Module[{f = #^2 - 2. &, x}, x = solver[f, 1., 6, 1.*^-15]; {x, f[x]}]
{1.41421, -4.44089*10^-16}
$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.