It may be simple but it does not generate uniformly distributed numbers...
Itis biased in favor of numbers of size 1000/10 (for a sum of 1000 and 10 numbers).
[Pseudo code]:
Create Array of size N
Create Integer of size Max
Loop through each element of N Except the last one
N(i) = RandomBetween (0, Max)
Max = Max - N(i)
End Loop
N(N) = Max
function [x,v] = randfixedsum(n,m,s,a,b)
% Rescale to a unit cube: 0 <= x(i) <= 1
s = (s-n*a)/(b-a);
% Construct the transition probability table, t.
% t(i,j) will be utilized only in the region where j <= i + 1.
k = max(min(floor(s),n-1),0); % Must have 0 <= k <= n-1
s = max(min(s,k+1),k); % Must have k <= s <= k+1
s1 = s - [k:-1:k-n+1]; % s1 & s2 will never be negative
s2 = [k+n:-1:k+1] - s;
w = zeros(n,n+1); w(1,2) = realmax; % Scale for full 'double' range
t = zeros(n-1,n);
tiny = 2^(-1074); % The smallest positive matlab 'double' no.
for i = 2:n
tmp1 = w(i-1,2:i+1).*s1(1:i)/i;
tmp2 = w(i-1,1:i).*s2(n-i+1:n)/i;
w(i,2:i+1) = tmp1 + tmp2;
tmp3 = w(i,2:i+1) + tiny; % In case tmp1 & tmp2 are both 0,
tmp4 = (s2(n-i+1:n) > s1(1:i)); % then t is 0 on left & 1 on right
t(i-1,1:i) = (tmp2./tmp3).*tmp4 + (1-tmp1./tmp3).*(~tmp4);
end
% Derive the polytope volume v from the appropriate
% element in the bottom row of w.
v = n^(3/2)*(w(n,k+2)/realmax)*(b-a)^(n-1);
% Now compute the matrix x.
x = zeros(n,m);
if m == 0, return, end % If m is zero, quit with x = []
rt = rand(n-1,m); % For random selection of simplex type
rs = rand(n-1,m); % For random location within a simplex
s = repmat(s,1,m);
j = repmat(k+1,1,m); % For indexing in the t table
sm = zeros(1,m); pr = ones(1,m); % Start with sum zero & product 1
for i = n-1:-1:1 % Work backwards in the t table
e = (rt(n-i,:)<=t(i,j)); % Use rt to choose a transition
sx = rs(n-i,:).^(1/i); % Use rs to compute next simplex coord.
sm = sm + (1-sx).*pr.*s/(i+1); % Update sum
pr = sx.*pr; % Update product
x(n-i,:) = sm + pr.*e; % Calculate x using simplex coords.
s = s - e; j = j - e; % Transition adjustment
end
x(n,:) = sm + pr.*s; % Compute the last x
% Randomly permute the order in the columns of x and rescale.
rp = rand(n,m); % Use rp to carry out a matrix 'randperm'
[ig,p] = sort(rp); % The values placed in ig are ignored
x = (b-a)*x(p+repmat([0:n:n*(m-1)],n,1))+a; % Permute & rescale x
return
6条答案
按热度按时间nwo49xxi1#
这里的正确答案是难以置信的简单。
想象一下一条白色,假设有1000个单位长。
你想用红色标记将这条线分成十部分。
很简单,选择九个随机数,并在每个点上画上红色油漆标记。
就这么简单。你完了!
因此,算法为:
(1)在0到1000之间随机选取9个数字(2)将9个数字,一个0和一个1000放入数组(3)使用“减法”对数组进行排序(4)获得数组值之间的10个“距离”
你完了。
(显然,如果你想在最终的集合中没有零,在第(1)部分中,如果你遇到冲突,只需重新选择另一个随机数。
理想情况下,作为程序员,我们可以在头脑中“看到”这样的可视化算法--无论我们做什么,都要尝试可视化地思考!
脚注-对于任何非程序员阅读这篇文章,请注意,这就像“你学习计算机科学时学到的第一件事!”也就是说,我没有得到任何信贷,我只是输入了琐碎的答案。
FTR另一个大家都知道的常见算法 * 假设你在处理分数 。得到10个随机数。将它们相加。 将它们乘以或除以某个数字,因此,总和就是所需的总和!* 如果处理分数,这很容易。
mjqavswn2#
也许是这样的
设置剩余的最大数量为目标数量
循环1到你想要的值的数量-1
得到一个从0到最大剩余量的随机数
将新的最大剩余量设置为旧的最大剩余量减去当前随机数
重复回路
最后你会得到一个“余数”,所以最后一个数字是由剩下的组成原始总数的任何东西决定的。
uqjltbpv3#
我相信@JoeBlow提供的答案在很大程度上是正确的,但 * 只有 * 当所需的“随机性”需要均匀分布时。在对该答案的评论中,@ Artefacon说:
这就引出了前面提到的关于这些数字的期望分布的问题。JoeBlow的方法 * 确实 * 确保了元素1与元素2具有相同的成为数字x的机会,这意味着它 * 必须 * 偏向大小为Max/n的数字。OP是否希望更有可能在接近Max的单个元素处射击或希望均匀分布在问题中没有明确说明。[抱歉-从术语的Angular 来看,我不确定这是否是一个'均匀分布',所以我只是用外行的话来称呼它]
总之,说一个元素的“随机”列表 * 必然 * 均匀分布是不正确的。缺失的元素,如上面其他评论所述,是期望的分布。
为了证明这一点,我提出了以下解决方案,其中包含随机分布模式的顺序随机数。如果第一个元素在0-N之间的任何数字上都有相同的机会,并且每个后续数字在0-[剩余总数]之间的任何数字上都有相同的机会,那么这样的解决方案将是有用的:
可能有必要在创建这些元素之后随机化它们的顺序,这取决于它们将如何使用[否则,每个元素的平均大小会随着每次迭代而减小]。
gzszwxb44#
生成10个随机数,直到10000。将它们从大到小排序:g0到g9
这将在整个范围内产生10个随机数,其加起来为10000。
gtlvzcf85#
更新:@Joe Blow有一个完美的答案。我的答案有一个特殊的功能,即生成大约相同大小的块(或者至少不大于(10000 / 10)),因此将其保留在适当的位置。
我想到的最简单、最快的方法是:
10000
)for
循环中的10个元素中的每一个元素。这将给予你一个随机值的数量,当添加,将导致最终值(忽略浮点问题)。
中途应该很容易实现。
但是,在某些时候,您将达到PHP的最大整数限制。不确定这在多大程度上可以用于十亿或更大的值。
i7uq4tfw6#
相关:http://www.mathworks.cn/matlabcentral/newsreader/view_thread/141395
请看这个MATLAB package。它附带了一个文件,其中包含实现背后的理论。
该函数生成随机的、均匀分布的向量x = [x1,x2,x3,...,xn]’,其具有指定的和s,并且对于指定的值a和b,我们具有a〈= xi〈= b。将这样的向量视为属于n维欧几里德空间并且位于约束到和s的n-1维超平面中的点是有帮助的。该问题可以容易地被重新缩放到a = 0和b = 1的情况,因此在本说明书中我们将假设情况就是这样,并且我们在单位n维“立方体”内操作。
以下是实现(© Roger斯塔福德):