Algorithm 随机生成一组长度为n,总计为x的数字
我正在做一个有趣的项目,我需要一个算法,如下所示: 生成长度为Algorithm 随机生成一组长度为n,总计为x的数字,algorithm,math,combinatorics,Algorithm,Math,Combinatorics,我正在做一个有趣的项目,我需要一个算法,如下所示: 生成长度为n的数字列表,这些数字加起来等于x 我愿意接受整数列表,但理想情况下,我希望留下一组浮点数 如果这个问题没有被认真研究,我会非常惊讶,但我不知道该找什么 我过去也曾处理过类似的问题,但这次的性质截然不同。在我生成一系列数字的不同组合之前,这些数字加起来就是x。我确信我可以简单地解决这个问题,但这似乎不是理想的解决方案 有人知道这叫什么,或者怎么说吗?谢谢大家 编辑:为了澄清,我的意思是列表的长度应该是N,而数字本身可以是任意大小 ed
n
的数字列表,这些数字加起来等于x
我愿意接受整数列表,但理想情况下,我希望留下一组浮点数
如果这个问题没有被认真研究,我会非常惊讶,但我不知道该找什么
我过去也曾处理过类似的问题,但这次的性质截然不同。在我生成一系列数字的不同组合之前,这些数字加起来就是x。我确信我可以简单地解决这个问题,但这似乎不是理想的解决方案
有人知道这叫什么,或者怎么说吗?谢谢大家
编辑:为了澄清,我的意思是列表的长度应该是N,而数字本身可以是任意大小
edit2:很抱歉我不正确地使用了“set”,我将它用作列表或数组的一个全面术语。很抱歉,我知道这造成了混乱。实际上,您需要将x划分为n个部分。这通常是通过以下方式完成的:将x划分为n个非负部分可以用以下方式表示:保留n+x自由位置,将n个边界放置到任意位置,将石头放置到其余位置。石头组加起来是x,因此可能的分区数量是(n+x\n) 所以你的算法可以是这样的:选择(n+x)-集的任意n子集,它唯一地确定x到n个部分的划分 在Knuth的TAOCP中,第3.4.2章讨论了随机抽样。请看这里的算法
算法S:(从总共n条记录中选择n条任意记录)
非整数的解决方案在算法上很简单:您只需选择任意n个总和不等于0的数字,然后用它们的总和对它们进行范数。这就是Python中的方法
import random
def random_values_with_prescribed_sum(n, total):
x = [random.random() for i in range(n)]
k = total / sum(x)
return [v * k for v in x]
基本上你选取n个随机数,计算它们的和,然后计算一个比例因子,这样的和就是你想要的
请注意,这种方法不会产生“统一”切片,也就是说,如果在所有具有给定总和的分布中随机选取,则您将得到的分布将更倾向于“平等”
要了解原因,您可以想象算法在两个数字具有规定总和(例如1)的情况下所做的操作:
点
p
是通过选取两个随机数获得的通用点,它在正方形[0,1]x[0,1]
内是一致的。点Q
是通过缩放P
获得的点,因此要求总和为1。从图中可以清楚地看出,靠近中心的点具有更高的概率;例如,将通过在对角线上投影任何点来找到正方形的精确中心(0,0)-(1,1)
,而点(0,1)
将只从(0,0)-(0,1)
中投影点。。。对角线长度为sqrt(2)=1.4142…
,而方形边仅为1.0
此代码的作用合理。我认为它产生了不同于6502答案的分布,但我不确定哪一个更好或更自然。当然,他的代码更清晰/更好
import random
def parts(total_sum, num_parts):
points = [random.random() for i in range(num_parts-1)]
points.append(0)
points.append(1)
points.sort()
ret = []
for i in range(1, len(points)):
ret.append((points[i] - points[i-1]) * total_sum)
return ret
def test(total_sum, num_parts):
ans = parts(total_sum, num_parts)
assert abs(sum(ans) - total_sum) < 1e-7
print ans
test(5.5, 3)
test(10, 1)
test(10, 5)
随机导入
def零件(总零件数和零件数):
points=[random.random()表示范围内的i(num\u parts-1)]
点。追加(0)
点。附加(1)
points.sort()
ret=[]
对于范围(1,len(点))内的i:
ret.append((点[i]-点[i-1])*总计)
回程网
def测试(总数、数量和部分):
ans=零件(总零件数和零件数)
资产负债表(总和-总和)<1e-7
打印ans
测试(5.5,3)
测试(10,1)
测试(10,5)
如果要在N-1
-由x1+x2+…+定义的维度空间中均匀采样xN=x
,那么您将看到一个特殊情况,即从。取样程序比为xi
生成均匀偏差稍微复杂一些。在Python中,有一种方法可以做到这一点:
xs = [random.gammavariate(1,1) for a in range(N)]
xs = [x*v/sum(xs) for v in xs]
如果您不太关心结果的采样属性,那么只需生成均匀偏差,然后更正它们的和。在python中:
a:创建一个(随机的0到1)倍总数的列表;将0和total追加到列表中
对列表排序,测量每个元素之间的距离
c:将列表元素四舍五入
import random
import time
TOTAL = 15
PARTS = 4
PLACES = 3
def random_sum_split(parts, total, places):
a = [0, total] + [random.random()*total for i in range(parts-1)]
a.sort()
b = [(a[i] - a[i-1]) for i in range(1, (parts+1))]
if places == None:
return b
else:
b.pop()
c = [round(x, places) for x in b]
c.append(round(total-sum(c), places))
return c
def tick():
if info.tick == 1:
start = time.time()
alpha = random_sum_split(PARTS, TOTAL, PLACES)
end = time.time()
log('alpha: %s' % alpha)
log('total: %.7f' % sum(alpha))
log('parts: %s' % PARTS)
log('places: %s' % PLACES)
log('elapsed: %.7f' % (end-start))
收益率:
[2014-06-13 01:00:00] alpha: [0.154, 3.617, 6.075, 5.154]
[2014-06-13 01:00:00] total: 15.0000000
[2014-06-13 01:00:00] parts: 4
[2014-06-13 01:00:00] places: 3
[2014-06-13 01:00:00] elapsed: 0.0005839
据我所知,此分布是统一的这是上述Javascript算法的一个版本
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
};
function getRandomArray(min, max, n) {
var arr = [];
for (var i = 0, l = n; i < l; i++) {
arr.push(getRandomArbitrary(min, max))
};
return arr;
};
function randomValuesPrescribedSum(min, max, n, total) {
var arr = getRandomArray(min, max, n);
var sum = arr.reduce(function(pv, cv) { return pv + cv; }, 0);
var k = total/sum;
var delays = arr.map(function(x) { return k*x; })
return delays;
};
然后再与
var sum = myarray.reduce(function(pv, cv) { return pv + cv;},0);
清楚地说,“长度
n
”是指整数的十进制表示形式,不带前导零,应该是n
位数,对吗?是否需要整数?如果没有,只需生成n
随机数,计算它们的和,并将它们缩小或放大到所需的和。@jwodder我为歧义感到抱歉,我编辑了我的问题,以澄清可能的重复,其中还讨论了一些微妙之处,这将起作用,除非所需的总数为零(将给出一个不太随机的输出),如果随机数之和恰好非常接近零(将爆炸或产生巨大的数字)。虽然这仍然是最好的解决方案,但可能需要做一些调整才能达到通用性。非常感谢,非常简单。我刚刚用javascript毫不费力地实现了它。请注意,这个分布在所有和x之和的n元组上是不一致的(即:并非所有n元组的可能性都相同)。很可能,只要输出看起来有点随机,询问者可能不会太在意。B
var sum = myarray.reduce(function(pv, cv) { return pv + cv;},0);