multiple CASE statements on interval within nested functions

后端 未结 2 1401
情歌与酒
情歌与酒 2021-01-15 01:13

Although I have come up with a work-around using multiple if / else if statements, I am curious in knowing what looks wrong with my case statement

相关标签:
2条回答
  • 2021-01-15 02:10

    The case expressions for your switch statement cannot be conditionals in MATLAB. They must be values.

    switch thing
        case 1
            % do thing
        case {2, 3}
            % do other thing
        otherwise
    end
    

    So what MATLAB is doing in your case, is that it is converting your conditionals into values. So when you supply a value of 0.073 what MATLAB sees is this.

    switch 0.73
        case 0
        case 0
        case 0
        case 1
        case 0
        case 0
        case 0
        otherwise
    end
    

    Since 0.73 obviously doesn't match any of those values you fall through to the otherwise and receive the error.

    This is why switch statements are really only best for categorical data where you are comparing the input value against exact possible values (obviously not good for a floating point number).

    A crazy solution

    If you REALLY want to keep this as a switch statement you could do a little trickery and actually make your switch expression simply "1" (true) and it will behave as you want it to.

    switch(1)
        case ((ar_vo >= 0)&&(ar_vo < 0.005))
            bucket=1;
        case ((ar_vo >= 0.005)&&(ar_vo < 0.02))
            bucket=2;
        case ((ar_vo >= 0.02)&&(ar_vo < 0.05))
            bucket=3;
        case ((ar_vo >= 0.05)&&(ar_vo < 0.1))
            bucket=4;
        case ((ar_vo >= 0.1)&&(ar_vo < 0.15))
            bucket=5;
        case ((ar_vo >= 0.15)&&(ar_vo < 0.25))
            bucket=6;
        case (ar_vo >= 0.25)
            bucket=7;
        otherwise
            error('MATLAB:RI Bucket:NotAvailable.');
    end
    

    Please don't actually do this.

    A Real Solution

    One sane approach is to use a series of if/elseif statements (as opposed to your long tree of if else if statements). This is a good approach (and is well-suited to floating point numbers) as it simply checks if that number is within a given range.

    if ((ar_vo >= 0)&&(ar_vo < 0.005))
        bucket=1;
    elseif ((ar_vo >= 0.005)&&(ar_vo < 0.02))
        bucket=2;
    elseif ((ar_vo >= 0.02)&&(ar_vo < 0.05))
        bucket=3;
    elseif ((ar_vo >= 0.05)&&(ar_vo < 0.1))
        bucket=4;
    elseif ((ar_vo >= 0.1)&&(ar_vo < 0.15))
        bucket=5;
    elseif ((ar_vo >= 0.15)&&(ar_vo < 0.25))
        bucket=6;
    elseif (ar_vo >= 0.25)
        bucket=7;
    else 
        error('MATLAB:RI Bucket:NotAvailable.');
    end
    

    The Best Solution

    What I personally would do though, would be to remove all of that code and simply replace it with the following statements.

    lowerlimits = [0, 0.005, 0.02, 0.05, 0.1, 0.15, 0.25]
    upperlimits = [lowerlimits(2:end), inf];
    
    bucket = find(ar_vo >= lowerlimits & ar_vo < upperlimits);
    
    if isempty(bucket)
        error('MATLAB:RI Bucket:NotAvailable.');
    end
    

    In this approach I compare ar_vo to all ranges simultaneously and then get the bucket value by using the index of the match. If there was no bucket assigned, there was no match, and bucket is an empty array.

    This drastically reduces the chance of copy/paste errors and makes it easier if you want to modify the conditions at a later date. It is likely also more performant particularly for values > 0.25 which would have to traverse your entire if/elseif construct.

    0 讨论(0)
  • 2021-01-15 02:10

    Building upon Suever's answer, and considering that you're actually trying to solve a data-binning problem, if you have R2015a or later, you can also use the built-in discretize function to achieve the same thing; e.g.:

    function bucket = ri(ar_vo,edgz)
      if nargin < 1
        edgz = [0, 0.005, 0.02, 0.05, 0.1, 0.15, 0.25, inf];
      end
      bucket = discretize(ar_vo,edgz);
      if isnan(bucket)
          error('MATLAB:RI Bucket:NotAvailable.');
      end
    end
    
    0 讨论(0)
提交回复
热议问题