Best method to define constants used by several functions

421 visualizaciones (últimos 30 días)
I am implementing a model in MATLAB that relies on several functions. All of these functions are dependent on the same set of constants, which currently are defined explicitly in each function (these are all in different m-files). My aim is to run the model several times with different values for the constants, and I'm looking for an easy way to adjust these constants without having to edit all individual functions. I think this may be done using global variables or by defining named constants, but as I've never used any of these methods before I don't know which approach is best or if there is an ever better way to do it.
Edit: One of the functions must remain a single-variable function, and the constants can thus not be passed along as input parameters.
  2 comentarios
Stephen23
Stephen23 el 28 de Sept. de 2017
Editada: Stephen23 el 28 de Sept. de 2017
Pass the values as input arguments. Global variables are the least recommended way of passing data between workspaces. You might like to read the many discussion on this forum related to global variables, e.g.:
If you have many values you should put them into an array (numeric, cell, struct, table,...) to make passing them around easier, and accessing is also simple using indexing/fieldnames/...
Cedric
Cedric el 28 de Sept. de 2017
Editada: Cedric el 28 de Sept. de 2017
In addition to the anonymous function/wrapper mentioned in the answers below, if you need these constants to be "real constants", you can create a class instead of a struct and declare them as constant properties. But this is a detail.
File Constants.m:
classdef Constants
properties( Constant = true )
radius = 28
height = -4
end
end
Then
>> C = Constants
C =
Constants with properties:
radius: 28
height: -4
>> C.radius
ans =
28
>> C.radius = 23
You cannot set the read-only property 'radius' of Constants.
PS: you can also access Constants.radius from anywhere if Constants.m is in the path, hence no need to pass extra parameters through wrappers. Yet, I'd use a wrapper (and it also makes you learn/train something about adapting interfaces using anonymous functions). One reason is that Constants.radius is not constant as it can be shadowed by a struct if you set a value to any of its properties:
>> clear all
>> class( Constants )
ans =
Constants
>> Constants.radius
ans =
28
>> Constants.radius = 89 ;
>> class( Constants )
ans =
struct
Accessing class properties is not like accessing objects properties. Classes are not variables but "extended types". When one tries to set/define a variable with the same name, however, MATLAB creates a new variable (in my example the struct Constants that has nothing to do with the homonym class).

Iniciar sesión para comentar.

Respuesta aceptada

Star Strider
Star Strider el 28 de Sept. de 2017
Change your functions to allow the constants to be passed as extra parameters, possibly as one parameter vector that can then be assigned to the individual variables in each of your functions.
I advise avoiding global variables at all costs. They can be inadvertently changed, and debugging code that uses global variables can be difficult.
  5 comentarios
Johanna Schmidt
Johanna Schmidt el 29 de Sept. de 2017
Thank you all! This helps me a lot. :)

Iniciar sesión para comentar.

Más respuestas (1)

John D'Errico
John D'Errico el 28 de Sept. de 2017
Use a struct, one that contains all of your parameters.
parms.a = 1;
parms.piapprox = 3.14;
parms.theanswertoeverything = 42;
Ok, I'm not feeling very creative. Now simply pass that variable around to all of your functions that will need any parameters.
function result = myfun(x,parms);
result = parms.piapprox*(x - parms.a).^2;
end
Or, you could write it as a function handle, like this:
myfun = @(x,parms) parms.piapprox*(x - parms.a).^2;
As you see, myfun is simple to evaluate.
myfun(3,parms)
ans =
12.56
And it is trivial to use fminbnd.
[xmin,fmin] = fminbnd(@(x) myfun(x,parms),-5,5)
xmin =
1
fmin =
0
  2 comentarios
teeeeee
teeeeee el 6 de Ag. de 2020
Hi John, I like this method of passing in a structure, but I have an additional question. In your function (not the handle version) you write result = parms.piapprox*(x - parms.a).^2; The problem is that if this expression becomes very long (say several tens of lines of code for a complex mathematical expresison), then it becomes cumbersome to refer to the variable as parms.piapprox. It would be nicer to just be able to refer to it as piapprox when you are inside the function, to cut down on all the repeating "parms." extra text.
Do you know of a nice way to automatically "unpack" the parms structure, so to speak, so we can use the field names directly? Ideally without doing something like this inside the function:
a = parms.a;
piapprox = parms.piapprox;
theanswertoeverything = parms.theanswertoeverything;

Iniciar sesión para comentar.

Productos

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by