2
$\begingroup$

This question already has an answer here:

This is my first question on Mathematica StackExchange, and I am fairly new to the Mathematica language.

This code aims to evaluate the root of f[x] == 0 between x-values a and b for any given f, and for a specified tolerance tol.

The code gives a Set::setraw error Set::setraw: Cannot assign to raw object 2., and the stack trace indicates that the error lies in the Do loop part.

What is causing the error, and how can I rectify it?

bisect[f_, a_, b_, tol_] := 
  Module[{n, mid, fm, root},
  {
    n = Ceiling[Log[2*((b - a)/tol)]]; (* number of iterations *)
    Do[
      mid = N[(a + b)/2];
      fm = N[f[x] /. x -> mid];
      If[fm < 0, a = N[mid], b = N[mid]],
      {j, 1, n}];
    root = N[(a + b)/2]
    Print["Root to f[x] = 0 is ", root];
  }];

(* calling program *)
f[x_] := x^2 - 0.9 Cos[x];
a = 0;
b = 2;
tol = 0.0001;
solution = bisect[f, a, b, tol]
$\endgroup$

marked as duplicate by corey979, m_goldberg, Coolwater, MarcoB, b3m2a1 Jan 19 '18 at 6:45

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ I think the question is more about basic Mathematica programming than about implementing an algorithm. -- Though the OP will probably appreciate seeing the alternatives in that Q&A. $\endgroup$ – Michael E2 Jan 7 '18 at 22:28
3
$\begingroup$

In a function, the parameters are not variables, but the symbols passed; if the symbols passed are numbers, you cannot assign them values. For example, in If[fm < 0, a = N[mid], b = N[mid]], when the function is called in the last line, a is 0 and b is 2. So for b = N[mid], what is executed is 2 = N[mid].

bisect[f_, a0_, b0_, tol_] := Module[{a, b, n, mid, fm, root},
   (*{ Mathematica is not C/Java: Braces always mean List[] *)
    a = N[a0];
    b = N[b0]; (* No more uses of N[] are needed *)
    n = Ceiling[Log[2*((b - a)/tol)]]; (* number of iterations *)

    Do[
     mid = N[(a + b)/2];
     fm = N[f[x] /. x -> mid];

     If[fm < 0, a = N[mid], b = N[mid]],
     {j, 1, n}
     ]; (* end do *)

    root = N[(a + b)/2];  (* You forgot a semicolon here *)
    Print["Root to f[x] = 0 is ", root]; (* most people would return root, not print it *)
    (*}*)
   ]; (* end module *)

(* calling program *)
f[x_] := x^2 - 0.9 Cos[x];
a = 0;
b = 2;
tol = 0.0001;
solution = bisect[f, a, b, tol]
$\endgroup$
  • $\begingroup$ Thanks for your help; after switching the order of assignments of the line with If, the error was fixed. Then, the solution was not being given properly. This is because of the semicolon I forgot. $\endgroup$ – szammit Jan 7 '18 at 22:22
  • $\begingroup$ @SamuelZammit You're welcome. :) $\endgroup$ – Michael E2 Jan 7 '18 at 22:34

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