variable usar una tipos numerica funciones funcion expresar definir declarar declaracion constantes como matlab constants matlab-class

usar - tipos de constantes en matlab



Constantes en MATLAB (8)

He adquirido la propiedad de un montón de código MATLAB y he notado un montón de "números mágicos" dispersos sobre el código. Normalmente, me gusta hacer esas constantes en lenguajes como C, Ruby, PHP, etc. Al buscar en Google este problema, encontré que la forma "oficial" de tener constantes es definir funciones que devuelven el valor constante. Parece kludgey, especialmente porque MATLAB puede ser complicado cuando permite más de una función por archivo.

¿Es esta realmente la mejor opción?

Estoy tentado de usar / hacer algo como el preprocesador C para hacer esto por mí. (Descubrí que algo llamado mpp fue creado por alguien más en una situación similar, pero parece abandonado. El código no se compila y no estoy seguro si satisfaría mis necesidades).


¡No myClass.myconst una constante usando myClass.myconst sin crear primero una instancia! A menos que la velocidad no sea un problema. Tenía la impresión de que la primera llamada a una propiedad constante crearía una instancia y luego todas las llamadas futuras harían referencia a esa instancia, ( Propiedades con valores constantes ), pero ya no creo que ese sea el caso. Creé una función de prueba muy básica de la forma:

tic; for n = 1:N a = myObj.field; end t = toc;

Con clases definidas como:

classdef TestObj properties field = 10; end end

o:

classdef TestHandleObj < handle properties field = 10; end end

o:

classdef TestConstant properties (Constant) field = 10; end end

Para diferentes casos de objetos, objetos de manejo, objetos anidados, etc. (así como operaciones de asignación). Tenga en cuenta que estos fueron todos escalares; No investigué matrices, celdas o caracteres. Para N = 1,000,000 mis resultados (para el tiempo total transcurrido) fueron:

Access(s) Assign(s) Type of object/call 0.0034 0.0042 ''myObj.field'' 0.0033 0.0042 ''myStruct.field'' 0.0034 0.0033 ''myVar'' //Plain old workspace evaluation 0.0033 0.0042 ''myNestedObj.obj.field'' 0.1581 0.3066 ''myHandleObj.field'' 0.1694 0.3124 ''myNestedHandleObj.handleObj.field'' 29.2161 - ''TestConstant.const'' //Call directly to class(supposed to be faster) 0.0034 - ''myTestConstant.const'' //Create an instance of TestConstant 0.0051 0.0078 ''TestObj > methods'' //This calls get and set methods that loop internally 0.1574 0.3053 ''TestHandleObj > methods'' //get and set methods (internal loop)

También creé una clase Java y ejecuté una prueba similar:

12.18 17.53 ''jObj.field > in matlab for loop'' 0.0043 0.0039 ''jObj.get and jObj.set loop N times internally''

La sobrecarga al llamar al objeto de Java es alta, pero dentro del objeto, las operaciones simples de acceso y asignación ocurren tan rápido como los objetos de Matlab regulares. Si desea que arranque el comportamiento de referencia, Java puede ser el camino a seguir. No investigué llamadas a objetos dentro de funciones anidadas, pero he visto algunas cosas raras. Además, el generador de perfiles es basura cuando se trata de muchas de estas cosas, por lo que pasé a guardar manualmente los tiempos.

Como referencia, la clase Java utilizada:

public class JtestObj { public double field = 10; public double getMe() { double N = 1000000; double val = 0; for (int i = 1; i < N; i++) { val = this.field; } return val; } public void setMe(double val) { double N = 1000000; for (int i = 1; i < N; i++){ this.field = val; } } }

En una nota relacionada, aquí hay un enlace a una tabla de constantes NIST: tabla ascii y una función matlab que devuelve una estructura con los valores listados: Matlab FileExchange


De cualquier forma que lo hagas, seguirá siendo algo así como un kludge. En proyectos anteriores, mi enfoque era definir todas las constantes como variables globales en un archivo de script, invocar el script al comienzo de la ejecución del programa para inicializar las variables, e incluir "MYCONST global"; declaraciones al comienzo de cualquier función que necesite usar MYCONST. Si este enfoque es superior a la forma "oficial" de definir una función para devolver un valor constante es una cuestión de opinión que uno podría discutir de cualquier manera. De ninguna manera es ideal.


MATLAB no tiene un equivalente exacto const. Recomiendo NO utilizar global para las constantes, por un lado, debe asegurarse de que estén declaradas donde quiera que las use. Crearía una función que devuelva los valores que desea. Puede consultar esta publicación en el blog para obtener algunas ideas.


Matlab tiene constantes ahora. El estilo más nuevo (R2008a +) "classdef" de Matlab OOP le permite definir propiedades de clase constante. Esta es probablemente la mejor opción si no requiere compatibilidad con versiones anteriores de Matlabs antiguo. (O, por el contrario, es una buena razón para abandonar la compatibilidad con versiones anteriores).

Defínalos en una clase.

classdef MyConstants properties (Constant = true) SECONDS_PER_HOUR = 60*60; DISTANCE_TO_MOON_KM = 384403; end end

Luego, haz referencia a ellos desde cualquier otro código usando la calificación de punto.

>> disp(MyConstants.SECONDS_PER_HOUR) 3600

Consulte la documentación de Matlab para "Programación orientada a objetos" en la "Guía del usuario" para obtener todos los detalles.

Hay un par de errores menores. Si el código accidentalmente intenta escribir en una constante, en lugar de obtener un error, creará una estructura local que enmascara la clase de constantes.

>> MyConstants.SECONDS_PER_HOUR ans = 3600 >> MyConstants.SECONDS_PER_HOUR = 42 MyConstants = SECONDS_PER_HOUR: 42 >> whos Name Size Bytes Class Attributes MyConstants 1x1 132 struct ans 1x1 8 double

Pero el daño es local. Y si desea ser minucioso, puede protegerse contra esto llamando al constructor MyConstants () al comienzo de una función, lo que obliga a Matlab a analizarlo como un nombre de clase en ese ámbito. (En mi humilde opinión esto es excesivo, pero está allí si lo deseas).

function broken_constant_use MyConstants(); % "import" to protect assignment MyConstants.SECONDS_PER_HOUR = 42 % this bug is a syntax error now

El otro problema es que las propiedades y los métodos de clase, especialmente las estadísticas como esta, son lentos. En mi máquina, leer esta constante es aproximadamente 100 veces más lento que llamar a una función simple (22 usec vs. 0.2 usec, vea esta pregunta ). Si está utilizando una constante dentro de un bucle, cópielo a una variable local antes de ingresar al bucle. Si por alguna razón debe usar el acceso directo de las constantes, vaya con una función simple que devuelva el valor.

Por el bien de tu cordura, mantente alejado de las cosas del preprocesador. Hacer que funcione dentro del Matlab IDE y el depurador (que son muy útiles) requeriría hacks profundos y terribles.


Mi forma de tratar las constantes que quiero pasar a otras funciones es usar una estructura:

% Define constants params.PI = 3.1416; params.SQRT2 = 1.414; % Call a function which needs one or more of the constants myFunction( params );

No es tan limpio como los archivos de encabezado C, pero cumple su función y evita los globales de MATLAB. Si quisiera que las constantes se definieran todas en un archivo separado (p. Ej., GetConstants.m), eso también sería fácil:

params = getConstants();


Normalmente solo defino una variable con UPPER_CASE y la coloco cerca de la parte superior del archivo. Pero debes tomar la responsabilidad de no cambiar su valor.

De lo contrario, puede usar clases MATLAB para definir constantes con nombre.


Puede que algunas de estas respuestas ¿Cómo creo tipos enumerados en MATLAB? útil. Pero, en resumen, no hay una forma de "una sola línea" de especificar variables cuyo valor no debería cambiar después de la configuración inicial en MATLAB.


Utilizo una secuencia de comandos con constantes simples en mayúsculas e incluyo la secuencia de comandos en otras secuencias de comandos tr = that beed them.

LEFT = 1; DOWN = 2; RIGHT = 3; etc.

No me importa que no sean constantes. Si escribo "IZQUIERDA = 3", entonces seré simple y estúpido y de todos modos no hay cura contra la estupidez, así que no me molesto. Pero realmente odio el hecho de que este método desordene mi espacio de trabajo con variables que nunca tendría que inspeccionar. Y tampoco me gusta usar sothing como "turn (MyConstants.LEFT)" porque esto hace que las afirmaciones más largas, como un trillón de caracteres, hagan que mi código no sea legible.

Lo que necesitaría no es una variable sino la posibilidad de tener constantes reales de precompilador. Es decir: cadenas que se reemplazan por valores justo antes de ejecutar el código. Así es como debería ser. Una constante no debería ser una variable. Solo está destinado a hacer que su código sea más legible y mantenible. MathWorks: POR FAVOR, POR FAVOR, POR FAVOR. No puede ser tan difícil implementar esto. . .