while - switch matlab simulink
mĂșltiples sentencias CASE en intervalos dentro de funciones anidadas (2)
Basándose en la respuesta de Suever , y considerando que en realidad está tratando de resolver un problema de agrupamiento de datos, si tiene R2015a o posterior, también puede usar la función incorporada de discretize
para lograr lo mismo; p.ej:
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
Aunque me he encontrado con una solución alternativa que utiliza varias declaraciones if / else if
, tengo curiosidad por saber qué parece mal con las declaraciones de mi case
, que se ilustra a continuación:
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
%
Dado ar_vo = 0.073...
al depurar el código, omite el case (4)
por alguna razón y llega al case (8)
...
Solución ineficiente pero funcional con múltiples 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
Las expresiones de case
para su declaración de switch
no pueden ser condicionales en MATLAB. Deben ser valores .
switch thing
case 1
% do thing
case {2, 3}
% do other thing
otherwise
end
Entonces, lo que MATLAB está haciendo en su caso, es que está convirtiendo sus condicionales en valores. Entonces, cuando usted suministra un valor de 0.073, lo que MATLAB ve es esto.
switch 0.73
case 0
case 0
case 0
case 1
case 0
case 0
case 0
otherwise
end
Dado que 0,73 obviamente no coincide con ninguno de esos valores, se cae en lo otherwise
y recibe el error.
Esta es la razón por la cual las declaraciones de cambio son en realidad las mejores para los datos categóricos en los que se compara el valor de entrada con los valores posibles exactos (obviamente no es bueno para un número de coma flotante).
Una solución loca
Si REALMENTE desea mantener esto como una declaración de cambio, podría hacer un pequeño truco y realmente hacer que su expresión de cambio sea simplemente "1" ( true
) y se comportará como usted lo desee.
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
Por favor, no hagas esto.
Una verdadera solución
Un enfoque sensato es usar una serie de enunciados if/elseif
(a diferencia de su árbol largo de sentencias if else if
). Este es un buen enfoque (y se adapta bien a los números de coma flotante) ya que simplemente verifica si ese número está dentro de un rango determinado.
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
La mejor solucion
Sin embargo, lo que personalmente haría sería eliminar todo ese código y simplemente reemplazarlo con las siguientes afirmaciones.
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
En este enfoque comparo ar_vo
a todos los rangos simultáneamente y luego obtengo el valor del bucket
usando el índice de la coincidencia. Si no se asignó un depósito, no hubo coincidencia y el bucket
es un conjunto vacío.
Esto reduce drásticamente la posibilidad de errores de copiar / pegar y facilita la modificación de las condiciones en una fecha posterior. Es probable que también sea más eficiente, particularmente para valores> 0.25 que tendrían que atravesar todo el constructo if/elseif
.