简体   繁体   中英

Inconsistencies in plotting piecewise functions in Matlab

For a mathematics course for first year university science students we (the teaching assistants) need to prepare material for pc-sessions using Matlab. All computers are equipped with Matlab version R2016b.

We are working through some material from the previous years. In the section covering the plotting of piecewise functions, we found some inconsistencies in the way Matlab handles an if condition.

I would like to know why these things happen so we are prepared for any difficulties the students might experience in these sessions. The goal of the exercise is to draw a house in the plotting window by plotting two piecewise functions.


The first function, f1(x) , evaluates to x+2 when x <= 0 and evaluates to -x+2 otherwise. The students are asked to implement this function in Matlab using an if / else construct. Our implementation is

function y = f1( x )
    if x < 0
        y = x + 2;
    else
        y = -x + 2;
    end
end

The second function, f2(x) , is the characteristic function of the interval [-1, 1]. It should also be implemented using if / else conditions. Our implementation is

function y = f2( x )
    if x < -1
        y = 0;
    elseif x > 1
        y = 0;
    else
        y = 1;
    end
end

Finally, the plotting code should draw both functions on the interval [-1.5, 1.5] using fplot like so

fplot(@f1, [-1.5, 1.5])
hold on
fplot(@f2, [-1.5, 1.5])

The function f2 is plotted without problems. In plotting f1 , however, it seems Matlab decided the first branch of the if-clause didn't matter as only the line -x+2 is plotted .

It seems vectorization issues lie at the heart of our problem since f1(-1) evaluates correctly to 1 but f1([-1, 1]) evaluates to [3, 1] . Then again, f2 seems to be evaluating correctly without any issues.

Things get stranger when we change the -x + 2 in the else part of f1 to -x^2 + 2 . With this definition both functions are plotted correctly and Matlab seems to have no problem dealing with the conditionals.

  1. What is going wrong?
  2. Is there a way we can edit the exercises such that it never poses any problems but is still accessible to students having their first experiences with Matlab?

In MATLAB if vector is like if all(vector) , and that is the source to your error. use indexing instead:

function y = f2( x )
y = zeros(size(x));  
idxs1 = x >= -1;
idxs2 = x <= 1;
y(idxs1 & idxs2) = 1;
end

function y = f1( x )
y = zeros(size(x));  
idxs = x < 0;
y(idxs) = x(idxs) + 2;
y(~idxs) = -x(~idxs) + 2;
end

fplot(@f1, [-1.5, 1.5])
hold on
fplot(@f2, [-1.5, 1.5])

在此输入图像描述

Using an If Statement

You say that you want to specifically use an if structure, in which case you will have to evaluate each element of the input vector in turn

function y = f1( x )
y = zeros(size(x));  % Initialise y to the correct size
for ii = 1:numel(x)  % Loop through elements of x (and so y)
    if x(ii) < 0
        y(ii) = x(ii) + 2;
    else
        y(ii) = -x(ii) + 2;
    end
end
end

This is because otherwise you may have the following issue:

x = [1, 2, -1, 3, -2];
% x < 0 = [0, 0, 1, 0, 1];
% "if x < 0" is the same as "if all(x < 0)" = false, so if statement skipped

Logical Indexing

If the course material can be changed / extended, then a much better option in Matlab is to leverage logical indexing.

x = [1, 2, -1, 3, -2];
y = -x + 2;     % Initialise variable y, assign its values to -x + 2 by default
y(x<0) = x + 2; % Assign values of y, where x<0, to x + 2

Now it can be seen how this can be done in a one liner...

coef = (x < 0)*2 - 1; % For the above example, coef = [-1, -1, 1, -1, 1];
y = coef.*x + 2;      % Coeff can be done in-line without being declared

So, with a similar (but even simpler) approach to f2 as well,

function y = f1(x)
    y = ((x<0)*2 - 1).*x + 2;
end

function y = f2(x)
    y = (abs(x) < 1);  
end

Then your demo gives the desired result

屋


As for your mysteries when changing part of the piecewise function and everything working... For me, your code all works anyway (2015b)! My guess is that this is something to do with how fplot is calling your functions. I currently can't access the docs, which may contain the answer. In my above examples, I'm assuming x is being passed as a vector (which may have 1 or more elements). If fplot determines the x values and calls the function as if for single points, then your code should work.

A way to edit the task to make things clearer may be to just use the normal plot function , which I think is more useful for students to be familiar with anyway.

Then your demo would be called like so

x = -1.5:0.1:1.5  % or could use linspace(-1.5, 1.5, 100) etc
hold on;
plot(x, f1(x));   % x,y syntax, more apparent where the points will be plotted
plot(x, f2(x));   %   than when using fplot
hold off;         % good habit to hold off so that you don't accidentally plot on this fig later

Notice that, with this clear definition of x , your -x^2 + 2 would throw an error as you are asking for matrix multiplication of a 1D vector. You would actually have to use -x.^2 + 2 . There's a cue for students to learn about element-wise operations in Matlab!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM