piecewise function evaluation using if-else statement

2 visualizzazioni (ultimi 30 giorni)
Hi, I have this code for a 'piecewise function' to be evaluated.
t = -10:0.01:10;
if t<0
F(1,:) = 2.*t;
elseif t<8
F(1,:) = sqrt(t);
else F(1,:) = t+1;
end
I was wondering why the output is different from the one I was expecting.
Expected output: all numbers below 0 must be twice that number.
Output:
-9 -8.99000000000000 -8.98000000000000 -8.97000000000000 -8.96000000000000 -8.95000000000000 -8.94000000000000 -8.93000000000000 -8.92000000000000 -8.91000000000000 -8.90000000000000 -8.89000000000000 -8.88000000000000 -8.87000000000000 -8.86000000000000…….

Risposta accettata

Roger Stafford
Roger Stafford il 16 Mar 2015
Matlab's 'if' statement requires that if the following condition is a multiple-element logical vector, then every one of these must be true for it to be executed. The same applies to the 'elseif' statement. The consequence for your example is that only the 'else' part is executed, which accounts for your results.
What I believe you want is:
F(1,:) = (t<0).*(2*t)+(t>=8).*(t+1)+(t>=0).*(t<8).*sqrt(t);
Either that, or you can use a for-loop to apply your original tests to the elements of t one at a time.
You can read about this in:
http://www.mathworks.com/help/matlab/ref/if.html
where it states that "An expression is true when its result is nonempty and contains only nonzero elements (logical or real numeric). Otherwise, the expression is false."
  2 Commenti
cgo
cgo il 16 Mar 2015
Wow, this is even more elegant that I thought. Thanks!
Walter Roberson
Walter Roberson il 10 Gen 2017
This condition .* value method often works really well. There is, however, a situation where it can give the wrong answer.
In each expression, the value is calculated for an element even if the condition is false for the element.
If the resulting value is finite, then it gets multiplied by the 0 corresponding to the condition being false for that element, and 0 .* finite gives 0 so you get out a 0 in that position, which is perfect for continuing on with the rest of the expression (one of the remaining expressions might give true and a non-zero value for that element.)
But if the resulting value calculation comes out as NaN or +/- inf, then when that is multiplied by 0, the result is NaN. And then when that NaN is added to anything else, the result is NaN, so you will get NaN in that position instead of some useful value.
A simple example is
(x == 0) .* 1 + (x ~= 0) .* (1./x)
The intent here is to give the value 1 at x = 0, and give 1/x otherwise. But the 1/x is calculated at all positions without checking the condition first, and so gives inf for 0, and the 0 (false) of x ~= 0, multiplied by inf, gives Nan instead of 0.
Karan's suggestion of using the new symbolic piecewise does not have this difficulty, but it does require that the input expression be symbolic, not plain numeric. If you have a numeric expression you might need to sym() it to use with piecewise()

Accedi per commentare.

Più risposte (2)

Adam
Adam il 16 Mar 2015
You can't use an if statement on a vector (or rather you can, but it is usually not the effect you wish to achieve, as in this case).
if t < 0
will test if the entire vector t is less than zero. It isn't. The else will test if the entire vector is less than 8. It isn't. Therefore the final else clause will be the one that kicks in and simply add 1 to all elements.
You can use vectorisation to achieve this as e.g.
t = -10:0.01:10;
F = t + 1;
F( t < 0 ) = 2 .* t( t < 0 );
F( t >= 0 & t < 8 ) = sqrt( t( t >= 0 & t < 8 ) );
Personally I would probably factor out that ugly condition that is used twice in the same line, but that is just semantics and personal preference.

Sally Al Khamees
Sally Al Khamees il 21 Feb 2017
If you have R2016b and the Symbolic Math Toolbox installed, you can just use the piecewise function:
t = -10:0.01:10;
syms y(t);
y(t) = piecewise(t<0, 2*t, 0 <= t <= 8, sqrt(t), t+1);
fplot(y,t)

Community Treasure Hunt

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

Start Hunting!

Translated by