problem using switch with logical operators, (larger than do this or less than do this)
Show older comments
Hi,
If anyone can help me explain why my code (below) does not work that would be very much appreciated. I would expect the results to be 'less than'.
Thanks
>> pos=-10000
switch pos
case pos==0
disp('equal')
case pos<0
disp('less than')
case pos>0
disp('more than')
otherwise
disp('not working')
end
pos =
-10000
not working
Accepted Answer
More Answers (5)
Jan
on 24 Jul 2011
The following would work, but I strongly recommend not to do this:
switch true % <-- difference is here
case pos==0 % triggers if: true == (pos==0)
disp('equal')
case pos<0
disp('less than')
case pos>0
disp('more than')
otherwise
disp('not working')
end
This takes the argument TRUE and compares it to the results of the comparisons in the CASE expressions. Although this is valid and documented, it is confusing - most of all for experienced programmers.
5 Comments
Oleg Komarov
on 24 Jul 2011
This looks like a (troll) solution!
Owen Morgan
on 27 Jul 2018
Could you say more about why this is not recommended and why it would be confusing to experienced programmers? To my untrained eyes, it looks at least as clear as the equivalent if/elseif/else statement.
In the majority of languages, the normal syntax is
switch name_of_variable_to_test
case possible_state_of_the variable
Anybody with experience writing code in other languages is going to expect that and will be very puzzled if confronted with the above.
Matlab is the only language I know where you can reverse this. The rule although stated in the documentation is not that simple (to the point that mathworks themselves have got it wrong in part of the documentation). For example, the below is allowed
switch var1 < 20
case var2 > 30
disp('case 1')
case sign(var3)
disp('case 2')
end
Can you tell me under which conditions case 1 or case 2 is displayed (just by reading the code)?
Walter Roberson
on 27 Jul 2018
I have been programming for over 40 years. Best Practices in programming is to write clearly and quickly understandably, except in cases where measured performance requires a less-clear form.
So if you want to compare a value to zero, then compare the value to zero,
if val < 0
...
elseif val == 0
...
else
...
end
instead of introducing the extra layer of introducing the constant true and comparing the result of a logical test to the constant
switch true
case val < 0
...
case val == 0
...
case val > 0
...
end
In nearly all programming languages, the syntax of switch is to switch on an expression with the cases being constants. Some programming languages implement that by using hash tables (in general) or lookup tables (in dense situations). Very few permit switching on an expression with the cases being expressions.
A way that would be acceptable would be
switch sign(val)
case -1
...
case 0
...
case 1
...
otherwise
%nan
end
Kevin Dixon
on 17 Feb 2021
The reason this question is being pushed out there is because MATLAB homeworks are being created to force us to use multiple methods to solve the same problem. Thank you Jan and Walter for showing how it can be done with switch instead of immediately saying use the if statement.
I am so tired of people making answers without actually answering the question. Just answer the question, and then state that there is a better way of doing it, then show that.
Again, thanks to the both of you.
Walter Roberson
on 24 Jul 2011
You are asking to "switch" based upon the value of pos, which means that the value of pos will be compared to the value of the expressions. The expressions you list are logical values, so they will all evaluate numerically to either 0 (false) or 1. As neither 0 nor 1 is equal to -10000, the "otherwise" will come in to effect.
If you look back at Oleg's answer, his answer is really the same, but with slightly less emphasis.
If you really wanted to, you could write
switch true
case pos==0
disp('equal');
case pos<0
disp('less than');
case pos>0
disp('greater than');
otherwise
disp('an error')
end
then the value true would be compared in turn to the logical values you list in the cases.
"switch" is not designed for classifying numbers in to ranges.
3 Comments
Jan
on 24 Jul 2011
Well, I have the feeling, that I have seen this code before... ;-)
Walter Roberson
on 24 Jul 2011
I was in the middle of answering when it became time to cook and eat dinner; by the time I got back and finished up the posting, you had developed the same code structure.
Kevin Dixon
on 17 Feb 2021
Thank you for actually answering the question, like Jan above. And not immediately say do it this way instead. Thanks again, this was an Actual MATLAB Grader problem, but with integraded equations.
Elin
on 24 Jul 2011
Edited: Walter Roberson
on 23 Dec 2024
1 Comment
Oleg Komarov
on 24 Jul 2011
As I wrote in my answer the case should be a value or a collection of values and pos == 0 is a value, "true". That's why I rewrote the swtich with the false/true.
What it does is it asks: is -1e4 false or is it true or is it false, otherwise.
Elin
on 24 Jul 2011
0 votes
Kelly Carter
on 17 Sep 2020
I disagree with some of the arguments above. I agree that a primary goal of coding should be clarity, but I disagree that one of the coding approaches is "unclear to experienced programmers" (I myself have over 40 years of coding, plus teaching coding at the university level). Below is a perfectly good and clear example of using the "switch true" type expression:
% Calculate basic tax
switch true
case (income >= 0 && income <= 6000)
tax = 0;
case (income > 6000 && income <= 34000)
tax = 0.15 * (income - 6000);
case (income > 34000 && income <= 80000)
tax = 4200 + 0.30 * (income - 34000);
case (income > 80000 && income <= 180000)
tax = 18000 + 0.40 * (income - 80000);
case (income > 180000)
tax = 58000 + 0.45 * (income - 180000);
otherwise
tax = 0;
disp('ERROR: Invalid income value');
end
3 Comments
Steven Lord
on 17 Sep 2020
That's one way to write that expression, but personally I'd probably use discretize to identify into which tax bracket each income falls and then logical indexing, grouptransform, groupsummary, splitapply, etc. to operate on the data from each bin (depending on what I wanted to do to the data.) The longest section of the code below is not the computation but storing the results in a table for easy viewing!
income = randi([0 200000], 10, 1); % Random sample incomes
bracketEdges = [0 6000 34000 80000 180000 Inf];
bin = discretize(income, bracketEdges);
results = table(income, bracketEdges(bin).', bracketEdges(bin+1).', ...
'VariableNames', ["income", "lowerLimit", "upperLimit"])
taxOnBracket2 = 0.15*(income(bin == 2) - 6000)
Kelly Carter
on 17 Sep 2020
Wow. Interesting solution. For those that thought the "switch true" construct was hard to read/understand, I'm guessing they'd really be stumped by your approach. I know my freshmen/sophmore college students would be clueless. Once one learns your approach and the "discretize" technique, it would be more readable. Thanks for sharing.
Walter Roberson
on 17 Feb 2021
Edited: Walter Roberson
on 17 Feb 2021
switch true was less than clear to me when I discovered it. I had questions such as:
- what order are the tests done in?
- what happens if more than one are true?
- since these are function evaluations, and function evaluations can have side effects, will evaluation of the case labels stop when there is a match?
- what happens if the function that is the case label does not return any output?
- if the switch is logical, do the case labels need to be logical, or will the common zero = false, non-zero = true hold, or will switch true only match numeric 1?
- does this mean more generally that you can switch on a numeric value and have the case labels be functions that return values that are compared to the value?
- if it does, then can you return a cell array and expect that the entries in the array will be compared to the value, or is the {} switch syntax syntactical rather than an actual cell array?
- if it is a functional cell array rather than a syntactical one, what do you return when you really do want a cell as the value
- is the syntax for listing a constant cell array to be tested against a scalar cell array switch, case {{scalar}} ?
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!