加到 100 的随机数:Matlab
Posted
技术标签:
【中文标题】加到 100 的随机数:Matlab【英文标题】:Random numbers that add to 100: Matlab 【发布时间】:2011-12-25 06:20:16 【问题描述】:[我正在将人口数拆分为不同的矩阵,现在想使用随机数测试我的代码。]
快速提问,提前感谢您的帮助 -
如果我使用;
100*rand(9,1)
这9个数字加100最好的方法是什么?
我想要 9 个 0 到 100 之间的随机数,加起来等于 100。
是否有一个内置命令可以执行此操作,因为我似乎找不到它。
【问题讨论】:
Non biased return a list of n random positive numbers (>=0) so that their sum == total_sum 的可能重复项 好问题,但重复:与语言无关的方面比与语言相关的部分重要得多。 这能回答你的问题吗? Getting N random numbers whose sum is M 【参考方案1】:我经常看到这个错误,建议生成具有给定总和的随机数,只需使用统一随机集,然后对其进行缩放。但是如果你这样做,结果真的是均匀随机的吗?
试试这个简单的二维测试。生成一个巨大的随机样本,然后将它们缩放到总和为 1。我将使用 bsxfun 进行缩放。
xy = rand(10000000,2);
xy = bsxfun(@times,xy,1./sum(xy,2));
hist(xy(:,1),100)
如果它们真的是均匀随机的,那么 x 坐标将是均匀的,y 坐标也是如此。任何价值都同样可能发生。实际上,要使两个点总和为 1,它们必须位于 (x,y) 平面中连接两个点 (0,1)、(1,0) 的直线上。为了使点均匀,沿该线的任何点的可能性都必须相等。
当我使用缩放解决方案时,显然均匀性失败了。这条线上的任何点都不太可能。我们可以看到同样的事情在 3 维中发生。看到这里的 3-d 图中,三角形区域中心的点更加密集。这反映了不均匀性。
xyz = rand(10000,3);
xyz = bsxfun(@times,xyz,1./sum(xyz,2));
plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
view(70,35)
box on
grid on
同样,简单的缩放解决方案失败了。它根本不会在感兴趣的领域产生真正统一的结果。
我们可以做得更好吗?嗯,是。二维中的一个简单解决方案是生成一个随机数,用于指定连接点 (0,1) 和 1,0) 沿线的距离。
t = rand(10000000,1);
xy = t*[0 1] + (1-t)*[1 0];
hist(xy(:,1),100)
可以证明,沿着由方程 x+y = 1 定义的直线上的任何点,在单位正方形中,现在都同样可能被选中。漂亮、平坦的直方图反映了这一点。
David Schwartz 建议的排序技巧是否适用于 n 维?很明显,它在 2-d 中这样做,下图表明它在 3-dimension 中这样做。在没有深入思考这个问题的情况下,我相信它会在 n 维的问题中适用于这个基本案例。
n = 10000;
uv = [zeros(n,1),sort(rand(n,2),2),ones(n,1)];
xyz = diff(uv,[],2);
plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
box on
grid on
view(70,35)
也可以从 Roger Stafford 贡献的文件交换中下载函数randfixedsum。这是在单位超立方体中生成真正均匀随机集的更通用的解决方案,具有任何给定的固定总和。因此,要生成位于单位 3 立方中的随机点集,受它们总和为 1.25 的约束...
xyz = randfixedsum(3,10000,1.25,0,1)';
plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
view(70,35)
box on
grid on
【讨论】:
我知道这是一个老问题,但谁能向我解释这个答案?你如何“生成一个随机数来指定沿着连接点 (0,1) 和 1,0) 的直线的距离。可以证明,沿着由方程 x+y = 1 定义的直线上的任何点,在单位方格中,现在同样有可能被选中。”?这甚至准确吗?我的部分困惑是,他为证明而发布的 Matlab 代码只是表明随机数是统一的,但它们并没有缩放到 1……这就是重点。 @jdfinch3:正在解决的问题是“选择一对数字 x, y 使得 x+y = 1。”解决方案是:“在 [0, 1] 范围内选择 x,然后计算 y = 1 - x”。这确保了对 (x, y) 是从所有可能对的宇宙中统一选择的。直方图表明它有效。 David Schwartz 的回答提供了对两个以上维度的概括(即具有两个以上元素的元组)。 @rici - 感谢您的回复!您对解决方案的重新措辞使它为我点击。 :) 证明 3 维相当容易:设两个随机数为 p 和 q,然后如果 p q 则 (q, p) 位于该三角形内。从 1 中减去较大的数字会将三角形映射到 (0,1)-(0,0)-(1,0),这是所需区域在 xy 平面上的投影,然后 z 就是 p 之间的差和 q 根据需要。对于更高的维度,我相信您可以将 N N-D 超金字塔包装在 N-D 超立方体中,这意味着对第 N 个随机数进行排序等同于选择合适的超金字塔。【参考方案2】:一种简单的方法是在 0 到 100 之间选择 8 个随机数。将 0 和 100 添加到列表中,得到 10 个数字。对它们进行排序。然后输出每对连续数字之间的差。例如,这里有 8 个 0 到 100 之间的随机数:
96、38、95、5、13、57、13、20
所以添加 0 和 100 并排序。
0、5、13、13、20、38、57、95、96、100
现在减去:
5-0 = 5 13-5 = 8 13-13 = 0 20-13 = 7 38-20 = 18 57-38 = 19 95-57 = 38 96-95 = 1 100-96 = 4
你有它,九个数字总和为 100:0、1、4、5、7、8、18、19、38。我得到一个零和一个只是一个奇怪的运气。
【讨论】:
太棒了!我喜欢它。我已经调整了你的方法来创建一系列总和为 0 的随机数。这允许我创建没有 net 效果的随机更改。 (即,移动的游戏精灵似乎或多或少地随机移动,但永远不会离开屏幕。^^) 这仅在您被允许使用介于 0 和您的总和之间的任何随机数时才有效!例如,当随机数的范围小于所需的总和时,这将不起作用。 该方法是正确的,但这个答案可以使用另一个编辑...这是一个包含 8 个数字的列表...添加 0 和 100(并从列表中默默地删除 20 以使总共九个数字)。答案以“九个数字加起来为 100:”结束,并继续列出八个数字。总体趋势是获取 N 个数字的列表,通过插入 0 和 100 创建一个 N+2 个数字的列表,然后将它们区分为总共 N+1 个数字并对结果进行排序。 @surgical:我修复了这个例子,我认为这只是一个简单的错误。我认为对最终元组进行排序会产生误导,但我会留给原作者来决定。 python 示例:>>> a = [0] + sorted([random.random()*100 for _ in range(9-1)]) + [100] >>> b = [a[i+1] - a[i] for i in range(len(a)-1)] >>> sum(b) == 100【参考方案3】:现在给出正确答案还为时不晚
让我们谈谈在 [0...1] 范围内对 X1...XN 进行采样,使得 Sum(X1, ..., XN) 等于 1。然后您可以将其重新缩放为 100
这称为Dirichlet distribution,下面是从中采样的代码。最简单的情况是当所有参数都等于 1 时,那么 X1、...、XN 的所有边际分布将是 U(0,1)。一般情况下,参数不等于 1s 时,边缘分布可能会有峰值。
-----------------取自here ---------------------
狄利克雷是单位尺度伽马随机变量的向量,通过它们的总和进行归一化。所以,没有错误检查,这会让你:
a = [1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0]; // 9 numbers to sample
n = 10000;
r = drchrnd(a,n)
function r = drchrnd(a,n)
p = length(a);
r = gamrnd(repmat(a,n,1),1,n,p);
r = r ./ repmat(sum(r,2),1,p);
【讨论】:
【参考方案4】:获取一个包含 N - 1 个数字的列表,通过插入 0 和 100 创建一个包含 N + 1 个数字的列表,对列表进行排序,然后将它们区分为总共 N 个数字。
【讨论】:
以上是关于加到 100 的随机数:Matlab的主要内容,如果未能解决你的问题,请参考以下文章