Matlab 如何在不知道何时停止的情况下将随机值重复添加到空向量中?如何计算平均步数?
想象一下,通过从空向量开始,然后在Matlab 如何在不知道何时停止的情况下将随机值重复添加到空向量中?如何计算平均步数?,matlab,random,montecarlo,Matlab,Random,Montecarlo,想象一下,通过从空向量开始,然后在v的末尾重复随机选择1到20的数字,形成向量v的过程。如何使用Matlab来调查在v包含从1到20的所有数字之前平均需要多少步?您可以在回答中定义/使用任意数量的函数或脚本 v=[]; v=zeros(1,20); for a = 1:length(v) v(a)=randi(20); end 因为v现在只是一个1x20向量,如果有两个数字相等,它肯定是 不是所有的20个数字都在1到20之间 for i = 1:length(v) for j = i
v
的末尾重复随机选择1到20的数字,形成向量v
的过程。如何使用Matlab来调查在v
包含从1到20的所有数字之前平均需要多少步?您可以在回答中定义/使用任意数量的函数或脚本
v=[];
v=zeros(1,20);
for a = 1:length(v)
v(a)=randi(20);
end
因为v
现在只是一个1x20向量,如果有两个数字相等,它肯定是
不是所有的20个数字都在1到20之间
for i = 1:length(v)
for j = i+1:length(v)
if v(i)==v(j)
v=[v randi(20)];
i=i+1;
break;
end
end
end
for k = 1:length(v)
for n = 1:20
if v(k)==n
v=v;
elseif v(k)~=n
a=randi(20);
v=[v a];
end
if a~=n
v=[v randi(20)];
k=k+1;
break;
end
end
end
disp('number of steps: ')
i*k
我不确定我是否正确理解了您的问题,但也许可以看看
unique()
函数
如果
那么向量中的所有值都是1:20
v = []
counter = 0;
while length(unique(v)) ~= 20
a = randi(20);
v=[v a];
counter = counter +1
end
值计数器
应提供在v包含所有值之前所需的迭代次数
如果您想通过试错法获得平均迭代次数,只需查看一下这段代码,并对其进行10000次测试,然后从
计数器中取结果的平均值 首先,生成向量的循环必须是无限的。如果你的条件得到满足,你可以跳出这个循环。这就是你如何计算你需要多少步骤。如果您知道需要更多的步骤,则不能使用超过20个步骤的循环。我喜欢使用而true
和break
接下来,确定是否存在所有元素的方法是O(n2)方法。这可以通过对元素进行O(n logn)排序来完成。这就是unique
所做的。它通过排序工作,在一般情况下,排序是O(n logn)(想想快速排序)。因此,绘制n
元素,并在每次检查它们是否都得到之后,都是一个操作O(n2 log n)。这太贵了
但我们这里讨论的是一组有限的整数。整数可以按O(n)排序(查找直方图排序或基数排序)。但我们可以做得更好,因为我们甚至不需要物理地创建向量或对其值进行排序。相反,我们可以简单地跟踪在长度为20的数组中看到的元素:在循环中,生成下一个向量元素,在20个元素的数组中设置相应的值,当该数组的所有元素都被设置时,您至少已经看到了所有值一次。这是你休息的时候
下面是我对这两种方法的实现。unique
方法需要11秒来重复10000次,而另一种方法只需要0.37秒。在10000次重复之后,我发现平均需要72步才能看到所有20个整数
function test
k = 10000;
tic;
n1 = 0;
for ii=1:k
n1 = n1 + method1;
end
n1 = n1 / k;
toc
disp(n1)
tic;
n2 = 0;
for ii=1:k
n2 = n2 + method2;
end
n2 = n2 / k;
toc
disp(n2)
end
function n = method1
k = 20;
v = [];
n = 1;
while true
v(end+1) = randi(k);
if numel(unique(v))==k
break;
end
n = n + 1;
end
end
function n = method2
k = 20;
h = zeros(20,1);
n = 1;
while true
h(randi(k)) = 1;
if all(h)
break;
end
n = n + 1;
end
end
注意计时:我在这里使用tic
/toc
,但通常最好使用timeit
。时间差足够大,所以这一点无关紧要。但一定要确保使用tic
/toc
的代码在函数中,而不是复制粘贴到命令行。在命令行上使用tic
/toc
时,计时不具有代表性,因为不会使用JIT编译器。stats.stackexchange上的以下问题包含一个Matlab模拟,询问您需要滚动六面模具多少次才能至少一次获得1-6之间的所有数字:非常感谢!!!这个很好用!!我希望这就是他们要问的。非常感谢!我只是matlab的初学者。。我还在想把我的“休息”放在哪里……我会学习你的第二种方法!
function test
k = 10000;
tic;
n1 = 0;
for ii=1:k
n1 = n1 + method1;
end
n1 = n1 / k;
toc
disp(n1)
tic;
n2 = 0;
for ii=1:k
n2 = n2 + method2;
end
n2 = n2 / k;
toc
disp(n2)
end
function n = method1
k = 20;
v = [];
n = 1;
while true
v(end+1) = randi(k);
if numel(unique(v))==k
break;
end
n = n + 1;
end
end
function n = method2
k = 20;
h = zeros(20,1);
n = 1;
while true
h(randi(k)) = 1;
if all(h)
break;
end
n = n + 1;
end
end