I would like to have a time domain function that uses a random number, but is stable over an interval. The anonymous function below does this, but it is not elegant.
f = @(t) {rng(ceil(t/10)), rand(1)}; % returns new random numbers each decade of t
f(2)
ans =
1×2 cell array
{1×1 struct} {[0.4170]}
The random number in second cell is what I want, but it can only be accessed through another variable. Is there a way in Matlab to simply return the random number without all the indirection?
Thank you for any help you can offer.

7 Kommentare

William Buller
William Buller am 22 Aug. 2026 um 16:15
Sometimes you just need to ask the question and then it comes to you!
f = @(t) isstruct(rng(ceil(t/10)))*rand(1);
Paul
Paul am 22 Aug. 2026 um 16:20
Are there bounds on t?
Matt J
Matt J am 22 Aug. 2026 um 16:36
f = @(t) isstruct(rng(ceil(t/10)))*rand(1);
Not a good idea. You are assuming sub-expressions in the function are evaluated left-to-right. That is not reliable.Why does the function have to be anonymous?
Walter Roberson
Walter Roberson am 22 Aug. 2026 um 20:20
MATLAB has a well-defined order of operations, that mostly guarantees left-to-right operations (as modified by the operation precedences, that leads to oddities like c^a^b ). The main exception is the vaguely-documented linear algebra exceptions where for example a'*b might be specially evaluated rather than being evaluated as (a')*b
Matt J
Matt J am 23 Aug. 2026 um 4:50
@Walter Roberson The order of operations is left-to-right, but not the order of computation of the operands.
Evidence?
format long g
e('+left',3)+e('+center',4)+e('+right',2)
+left +center +right
ans =
9
e('*left',3)*e('*center',4)*e('*right',2)
*left *center *right
ans =
24
e('.*left',3).*e('.*center',4).*e('.*right',2)
.*left .*center .*right
ans =
24
e('.^-left',3).^-e('.^-center',4).^-e('.^-right',2)
.^-left .^-center .^-right
ans =
6561
e('&&left',3)&&e('&&center',4)&&e('&&right',2)
&&left &&center &&right
ans = logical
1
e('|&left',3)|e('|&center',4)&e('|&right',2)
|&left |&center |&right
ans = logical
1
function v = e(where,v)
disp(where);
end
Paul
Paul am 23 Aug. 2026 um 12:38
Is there any documentation that prescribes the order of computation of the operands for an arithmetic operator? I can't find it, and therefore wouldn't assume any specific behavior.
I was curious about other languages. The AI result (whatever that's worth) from google for C was:
"In C, the order of evaluation for operands of most operators is unspecified. The compiler can evaluate them in any order it wants.
...
Important Rules to Remember
  • No general left-to-right rule: For normal binary operators like + or -, f1() + f2() does not guarantee that f1() runs first.
  • Function arguments: The order of evaluation for function arguments is also unspecified."
Related discussion here Is the Order of Function Evaluation Guaranteed when Function Outputs are Concatenated into an an Array? - MATLAB Answers - MATLAB Central on order of computation when constructing matrices via concatenation, which also includes discussion on order of computation of operands in expressions with arithmetic operators.

Melden Sie sich an, um zu kommentieren.

 Akzeptierte Antwort

Walter Roberson
Walter Roberson am 22 Aug. 2026 um 20:02
f = @(t) struct('rng', rng(ceil(t/10)), 'r1', rand(1)).r1
f = function_handle with value:
@(t)struct('rng',rng(ceil(t/10)),'r1',rand(1)).r1
f(2)
ans = 0.4170

6 Kommentare

Matt J
Matt J am 23 Aug. 2026 um 4:53
Bearbeitet: Matt J am 23 Aug. 2026 um 5:00
I wouldn't trust this, at least not for posterity. Can we be sure struct() will always generate the fields in left to right order? Can we even be sure both struct fields will be assigned before the .r1 operation is applied?
Walter Roberson
Walter Roberson am 23 Aug. 2026 um 8:59
Yes, we can be sure that the first field will be calculated before the second field, and we can be sure both struct field will be assigned before that dereferencing. struct is not a special operator, so it is bound by the general rule that operands are evaluated left to right -- first the character vector 'rng' then rng(ceil(t/10)) then the character vector 'r1' then rand(1) . Once those are evaluated, they are pushed on the stack for the call to struct and the call to struct is made. The call to struct returns a structure, and then the . operator dereferences a field of the structure.
The functionality of using dot indexing off of the result of an expression is documented somewhere; unfortunately I do not find the relevant portion of documentation at the moment.
struct is a built-in function
exist struct
ans = 5
Does the documentation prescribe that arguments to a built-in function call are evaluated one-at-a-time and left-to-right? I can't find anything.
Matt J
Matt J am 23 Aug. 2026 um 13:58
Bearbeitet: Matt J am 23 Aug. 2026 um 13:59
Even if that were true now, will it always be, and why would TMW commit to it? See also @Paul's comment.
struct's implementation is built-in -- which means it is implemented as compiled code rather than as .m code.
struct is not, however, a special function. parameters to struct as calculated the same way nearly everything is calculated.
The only special functionality that I can think of at the moment is:
  • int64() and uint64() enclosing an integer constant with no operators, causes the enclosed constant to be parsed as 64 bit. This is special behaviour: normally the enclosed constant would be parsed as double precision and the resulting double precision would be passed to the function
  • certain linear algebra expression sequences are specially evaluated, such as A'*B is not evaluated as (A')*B
  • the || and && short circuit operators might not execute the right-hand-side operands
e('&&left_true', 2) && e('&&right_true', 3)
&&left_true &&right_true
ans = logical
1
e('&&left_false',0) && e('&&right_true', 3)
&&left_false
ans = logical
0
e('&&left_true', 2) && e('&&right_false', 0)
&&left_true &&right_false
ans = logical
0
e('&&left_false', 0) && e('&&right_false', 0)
&&left_false
ans = logical
0
function v = e(cond, v)
disp(cond);
end
Paul
Paul am 23 Aug. 2026 um 21:02
Yes, struct is a built-in function and there is nothing special about it, which was exaclty my point, i.e., there is no documentation on the order of argument evaluation in a function call (at least not that I can find). If it's not documented, then it's "undefined behavior" and one takes one's chances when relying on undefined behavior, which can change from one release to the next, or coulde even be different within a release. I'm not suggesting that in this particular use case that the risk is large, but it's not non-zero until Mathworks says so.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (4)

Matt J
Matt J am 22 Aug. 2026 um 16:20
Bearbeitet: Matt J am 22 Aug. 2026 um 16:20

0 Stimmen

function y=f(t)
rng(ceil(t/10));
y=rand(1);
end
Paul
Paul am 22 Aug. 2026 um 16:38
t = 2*(rand(1,1000)-0.5)*100;
figure
plot(t,f(t,10),'b.',t,f(t,10),'r.')
function y = f(t,interval)
tinterval = ceil(t/interval);
[C,ia,ic] = unique(tinterval);
yout = rand(size(C));
y = yout(ic);
end
Matt J
Matt J am 22 Aug. 2026 um 16:48

0 Stimmen

rng('default')
T= rand(1,10);
t=1:15;
T(ceil(t/10))
ans =
Columns 1 through 9
0.8147 0.8147 0.8147 0.8147 0.8147 0.8147 0.8147 0.8147 0.8147
Columns 10 through 15
0.8147 0.9058 0.9058 0.9058 0.9058 0.9058
Steven Lord
Steven Lord am 23 Aug. 2026 um 2:48
Bearbeitet: Steven Lord am 23 Aug. 2026 um 5:51
If you can use a "named" function like Matt J's answer that would proably be cleanest.
But if you want to draw numbers from a random number generator with a particular seed value and they must be generated inside an anonymous function, without defining a "named" function, rng is not the right tool for this particular application. Use RandStream.create. This creates a temporary random number generator object from which you can draw numbers without affecting any other rand, randn, randi, etc. call.
f = @(t) rand(RandStream.create('twister', 'seed', t), 1, 2)
f = function_handle with value:
@(t)rand(RandStream.create('twister','seed',t),1,2)
f(1)
ans = 1×2
0.4170 0.7203
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
f(2)
ans = 1×2
0.4360 0.0259
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
f(1)
ans = 1×2
0.4170 0.7203
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
rng(2, 'twister')
rand(1, 2) % Matches f(2)
ans = 1×2
0.4360 0.0259
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
rng(1, 'twister')
f(3) % doesn't affect the global generator [SL fixed typo]
ans = 1×2
0.5508 0.7081
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
rand(1, 2) % Matches f(1)
ans = 1×2
0.4170 0.7203
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>

Kategorien

Produkte

Version

R2025a

Gefragt:

am 22 Aug. 2026 um 16:07

Kommentiert:

am 23 Aug. 2026 um 21:02

Community Treasure Hunt

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

Start Hunting!

Translated by