find all answers of an equation

15 views (last 30 days)
sina farahi
sina farahi on 21 Feb 2015
Edited: per isakson on 20 Dec 2017
how can I solve the equation
exp(-0.2*x)==(x-2)*(x-3)*x
without plotting??I tried "solve""fzero"and some others but I couldn't do it.I wann'a all answers without ploting......thanks

Accepted Answer

Star Strider
Star Strider on 21 Feb 2015
No plotting, simply a for loop:
f = @(x) (x-2).*(x-3).*x - exp(-0.2*x);
x = [-5:0.1:5];
for k1 = 1:length(x)
rt(k1) = fzero(f, x(k1));
end
rt = unique(round(rt*1E+8)/1E+8);
produces:
rt =
189.1722e-003 1.6777e+000 3.1475e+000
The unique call is necessary because fzero will find the same approximate root for similar values of ‘x’ as it loops. Due to the characteristic approximation errors of fzero and inherent floating-point approximation errors, it is necessary to use a modified version of the round function to correct those. The roots are therefore good to about 1E-8.
  2 Comments
Star Strider
Star Strider on 21 Feb 2015
My pleasure!
I will be glad to explain them. First, I created your equation as an anonymous function (see the documentation on Anonymous Functions for details) so that fzero could evaluate it. Since fzero finds the points where the function equals zero, it was necessary to rearrange your equation to be in that form.
Second, I considered only the real roots of your equation, and so limited myself to finding them. I began with a plot to see what the behaviour of your function was. It appeared to have no real roots outside [-5,5], so I created a vector ‘x’ that spanned that interval to use as starting values for fzero. I then looped through those values, recording in the ‘rt’ vector the roots that fzero found.
I then used the unique function (as I described) to isolate the three roots to an acceptable degree of precision.

Sign in to comment.

More Answers (1)

John D'Errico
John D'Errico on 21 Feb 2015
Edited: John D'Errico on 21 Feb 2015
How will you KNOW that you have found all solutions?
Wanting something is nice. Of course, we can't always get what we want. Hmm. That brings to mind a song, but odds are you have no idea what the reference to The Rolling Stones means. Kids, whats the matter with kids these days... (oops, now another song running through my head.)
Essentially, you cannot know that you have found all solutions to a nonlinear problem quite so easily. Mathematics is unforgiving. It does not give up its gifts without some effort on your part. In fact, even a plot is not in general sufficient, but it helps.
You MIGHT try this...
x1 = vpasolve(exp(-0.2*x)-(x-2)*(x-3)*x);
Then having solved for one root, deflate that root.
x2 = vpasolve((exp(-0.2*x)-(x-2)*(x-3)*x)/(x - x1));
and so on...
x3 = vpasolve((exp(-0.2*x)-(x-2)*(x-3)*x)/(x - x1)/(x-x2));
The general idea is to divide by the root you just found. This produces a new function that no longer has a root there. It works ok, at least until you have a problem with a root of order greater than 1, but then those roots will always cause a problem.
Anyway, where will this stop? How do you know that you have found all solutions? Again, knowing is the problem.
Alternatively, you might also try this...
expapprox = taylor(exp(-0.2*x)-(x-2)*(x-3)*x,'order',12)
expapprox =
- x^11/1949062500000000 + x^10/35437500000000 - x^9/708750000000 + x^8/15750000000 - x^7/393750000 + x^6/11250000 - x^5/375000 + x^4/15000 - (751*x^3)/750 + (251*x^2)/50 - (31*x)/5 + 1
vpasolve(expapprox)
ans =
0.18917220177346115933136958626227
1.6777208821198268365498168943942
3.1475285196592919001051461341551
- 24.981498513455838504331503293085 - 77.635564933596272665477129914466*i
- 66.383256811003489391804191913618 - 33.088493220112188173092823906644*i
36.30488877539236675241567653391 + 76.669938475166864616233334038753*i
80.052655747290671195726852365387 + 31.634706205534754641970685588937*i
80.052655747290671195726852365387 - 31.634706205534754641970685588937*i
- 24.981498513455838504331503293085 + 77.635564933596272665477129914466*i
36.30488877539236675241567653391 - 76.669938475166864616233334038753*i
- 66.383256811003489391804191913618 + 33.088493220112188173092823906644*i
That vpasolve found 3 real roots to the approximate problem might be a clue, but it was only an approximation. And that approximation may have either missed a root, or introduced a spurious one. In fact, we see many complex roots that it found.
There are other tricks one can employ, although it is in general difficult to know how to find all solutions to a nonlinear problem. For example, you can evaluate your function at a sequence of points, looking for zero crossings. At any point where you find a zero crossing, this will be a bracket for fzero.
fun = @(x) (exp(-0.2*x)-(x-2).*(x-3).*x);
x = -10:.05:10;
>> ind = find(diff(sign(fun(x))))
ind =
204 234 263
[x(ind);x(ind+1)]'
ans =
0.149999999999999 0.199999999999999
1.65 1.7
3.1 3.15
So now we would just run fzero in a loop on those three brackets where we think a root might lie. In fact, the work we did above should convince you that fzero will succeed on those brackets.
So it looks like we may have found brackets around at least 3 roots. I say may here, because there are always things that can mess up such a scheme. For example, find the root of tan(x) in the interval [1.5,1.6]. In fact, this is a bracket, in the sense that tan(x) changes sign over that interval. But is there a root in there?
For a general function, there may be infinitely many solutions, or there may be solutions that are difficult to find. And depending on the method you use, it always helps to test those solutions to see if they really were solutions to your original problem. There are always many ways to solve any problem, but understanding the methods you will use is important. Can they fail? How will you know if they have failed? Finally, in the end, a plot really does help. Allow your eyes and your brain to help you out.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!