【问题标题】:multiple CASE statements on interval within nested functions嵌套函数中间隔的多个 CASE 语句
【发布时间】:2016-03-10 14:29:23
【问题描述】:

虽然我想出了一个使用多个if / else if 语句的解决方法,但我很想知道我的case 语句看起来有什么问题,如下图所示:

function [ar_vo,bucket] = revEng(v)
...
s=solve(solve>0) * sqrt(T); 
ar_vo=s; 
bucket=ri(ar_vo);
%%%%%%%%%%%%%%%%%%%%%
function bucket = ri(ar_vo)
%          switch(ar_vo)
%              case ((ar_vo >= 0)&&(ar_vo < 0.005)) (1)
%                   bucket=1;
%              case ((ar_vo >= 0.005)&&(ar_vo < 0.02)) (2)
%                   bucket=2;
%              case ((ar_vo >= 0.02)&&(ar_vo < 0.05)) (3)
%                   bucket=3;
%              case ((ar_vo >= 0.05)&&(ar_vo < 0.1)) (4)
%                   bucket=4;
%              case ((ar_vo >= 0.1)&&(ar_vo < 0.15)) (5)
%                   bucket=5;
%              case ((ar_vol >= 0.15)&&(ar_vol < 0.25)) (6)
%                   bucket=6;
%              case (ar_vo >= 0.25)                     (7)
%                   bucket=7;
%              otherwise
%                   error('MATLAB:RI Bucket:NotAvailable.'); (8)
%          end
%      

在调试代码时给定ar_vo = 0.073...,由于某些原因它会跳过case (4)并到达case (8)...

低效但有效的解决方案,有多个if / else if

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

【问题讨论】:

  • 我多语言切换的情况需要中断;声明表示,我们不想通过其余的 case 语句,而是要完成 switch。不知道是不是这样
  • 好的...,但肯定不在matlab 中,因为我有时将它用于处理间隔(使用float 数据类型)之外的其他目的而没有问题。

标签: matlab switch-statement case


【解决方案1】:

MATLAB 中 switch 语句 cannot be conditionalscase 表达式。它们必须是

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

那么 MATLAB 在您的情况下所做的是将您的条件 转换为 值。因此,当您提供 0.073 的值时,MATLAB 看到的是这个。

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

由于 0.73 显然不匹配任何您落入 otherwise 并收到错误的值。

这就是为什么 switch 语句实际上只最适合用于将输入值与 exact 可能值进行比较的分类数据(显然不适合浮点数)。

一个疯狂的解决方案

如果您真的想将其保留为 switch 语句,您可以做一些小把戏,实际上使您的 switch 表达式简单地“1”(true)和它会按照您的意愿行事。

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

请不要实际上这样做。

真正的解决方案

一种理智的方法是使用一系列if/elseif 语句(而不是if else if 语句的长树)。这是一个很好的方法(并且非常适合浮点数),因为它只是检查该数字是否在给定范围内。

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

最佳解决方案

个人会做的是删除所有代码并简单地用以下语句替换它。

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

在这种方法中,我将ar_vo 与所有范围同时 进行比较,然后使用匹配的索引获得bucket 值。如果没有分配桶,则没有匹配,bucket 是一个空数组。

这大大减少了复制/粘贴错误的机会,并且如果您想在以后修改条件更容易。特别是对于必须遍历整个 if/elseif 构造的 > 0.25 的值,它的性能也可能更高。

【讨论】:

  • 对您的反馈质量感到惊讶。非常感谢您的解释,以及The Best Solution 体现的smart 反馈。
【解决方案2】:

Suever's answer 的基础上,考虑到您实际上是在尝试解决数据分箱问题,如果您有R2015a 或更高版本,您还可以使用内置的discretize实现相同功能的功能;例如:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-12
    • 2016-12-10
    相关资源
    最近更新 更多