while switch matlab switch-statement case

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 .