I have tried to implement a bisection method for finding roots using SetAttributes[BisectionItt, HoldAll] and then SetAttributes[BisectionItt, First]; both to no avail. I have tried reading up on the issue, but I can't seem to implement anything that works.

I want a function implementing the following form:

Bisection[left initial, right initial, function, number of iterations] -> estimate of root

Here is my code:

Bisection[a0_, b0_, function_, itt_] :=
    a = N[a0];
    b = N[b0];
    m = (a+b)/2;
    If[function[m] > 0, a = m, b = m];
    If[itt  < 0, 
      Return[Bisection[a, b, function, itt--]]];]

f[x_] := x^3 - 5 x + 1;
Bisection[0, 1, f, 7]

I believe that this a pass by value/reference issue. I would be very grateful if someone could show me a working example.

  • $\begingroup$ Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Take the tour and check the faqs! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! $\endgroup$ – Chris K Oct 22 '18 at 11:34
  • $\begingroup$ Related: mathematica.stackexchange.com/questions/69771/… $\endgroup$ – Michael E2 Oct 23 '18 at 10:49

Running your code produces the error Decrement::rvalue: 7 is not a variable with a value, so its value cannot be changed. That made me look at the itt-- part. Using -- attempts to change the variable itt, which can't be done here since it's an argument of your function. All you need to do is replace itt-- by itt-1 and your code works fine.

P.S., if a,b,m are local variables, you can put them in the {} after Module[.

| improve this answer | |

Many ideas imported from procedural programming languages don't fit Mathematica. Mathematica is an expression rewriting language. If I have a definition:

foo[x_]:= an expression

That means "when you see foo[something], evaluate something and then replace every x in an expression with the result and then evaluate an expression". So, if you evaluate foo[1], all instances of x in an expression are replaced by 1 before evaluating an expression. Here, x is not a variable, but the name of a pattern that matches an argument.

Your Module isn't needed. Module is a symbol localization construct, but you are giving it an empty list of symbols to localize. The only thing it's doing is giving Return something to return from, but you don't need Return. Return doesn't do what you think it does. Don't use it until you understand what it does. Then you'll almost never use it.

| improve this answer | |

My favorite way to implement the bisection method is as follows.

      bisectStep[f_, {aStart_, bStart_}] :=
            {a = N[Min[aStart, bStart]], b = N[Max[aStart, bStart]], fa, c, fc},
            fa = f[a];
            c = Mean[{a, b}]; fc = f[c];
            If[Sign[fa] != Sign[fc], b = c, a = c];
            {a, b}

      bisect[f_, a_, b_, \[Delta]_] := 
         Mean /@ NestWhileList[bisectStep[f, #] &, {1, 2}, (Subtract @@ Reverse[#] > \[Delta]) &]

It is used as follows:

      bisect[f, 1, 2, 0.00001]

Note that:

  • the output consists of the midpoints of the successive intervals; and
  • the stopping test is closeness of successive $x$-values (and not smallness of magnitude of function values).

If you want to see more than the default number of decimal places in the output, use NumberForm, e.g.:

      bisect[f, 1, 2, 0.00001] // NumberForm[#, 10] &
| improve this answer | |

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