【问题标题】:Generating random numbers to obtain a fixed sum(python) [duplicate]生成随机数以获得固定总和(python)[重复]
【发布时间】:2018-09-14 22:43:01
【问题描述】:

我有以下清单:

Sum=[54,1536,36,14,9,360]

我需要生成 4 个其他列表,其中每个列表将由 6 个从 0 开始的随机数组成,这些数字将加起来为总和。例如;

l1=[a,b,c,d,e,f] where a+b+c+d+e+f=54
l2=[g,h,i,j,k,l] where g+h+i+j+k+l=1536

等等直到l6。我需要在 python 中执行此操作。能做到吗?

【问题讨论】:

  • 当然可以,但首先你必须决定你打算如何选择随机数。我可以只做[random.randrange(2) for _ in range(5)] 然后为我的最后一个随机数添加1536 - sum(those five numbers) 吗?如果不是,为什么不呢?这里有什么规则?
  • 这是一道作业题吗?请向我们展示您迄今为止在代码方面所做的尝试。
  • @abertnet,没有这样的规则,只是数字必须是随机的
  • 是否有任何限制,比如数字不应该重复,或者类似的东西?

标签: python list numpy random


【解决方案1】:

生成一个总和为某个整数的随机数列表是一项非常困难的任务。跟踪剩余数量并使用剩余可用数量按顺序生成项目会导致分布不均匀,其中系列中的第一个数字通常比其他数字大得多。最重要的是,最后一个总是不为零,因为列表中的前面的项目永远不会总和达到所需的总数(随机生成器通常使用最大的开放间隔)。生成后重新排列列表可能会有所帮助,但通常也不会产生好的结果。

一种解决方案可能是生成随机数,然后对结果进行归一化,如果您需要它们为整数,则最终将其四舍五入。

import numpy as np
totals = np.array([54,1536,36,14])  # don't use Sum because sum is a reserved keyword and it's confusing

a = np.random.random((6, 4))  # create random numbers
a = a/np.sum(a, axis=0) * totals  # force them to sum to totals

# Ignore the following if you don't need integers
a = np.round(a)  # transform them into integers
remainings = totals - np.sum(a, axis=0)  # check if there are corrections to be done
for j, r in enumerate(remainings):  # implement the correction
    step = 1 if r > 0 else -1
    while r != 0:
        i = np.random.randint(6)
        if a[i,j] + step >= 0:
            a[i, j] += step
            r -= step

a 的每一列代表您想要的列表之一。 希望这会有所帮助。

【讨论】:

【解决方案2】:

这可能不是最有效的方法,但它会起作用

totals = [54, 1536, 36, 14]

nums = []
x = np.random.randint(0, i, size=(6,))
for i in totals:
    while sum(x) != i: x = np.random.randint(0, i, size=(6,))
    nums.append(x)
print(nums)

[数组([ 3, 19, 21, 11, 0, 0]), 数组([111, 155, 224, 511, 457, 78]), 数组([ 8, 5, 4, 12, 2, 5]), 数组([3, 1, 3, 2, 1, 4])]


这是一种更有效的方法

总数 = [54,1536,36,14,9,360, 0]

nums = []
for i in totals:
    if i == 0: 
        nums.append([0 for i in range(6)])
        continue
    total = i
    temp = []
    for i in range(5):
        val = np.random.randint(0, total)
        temp.append(val)
        total -= val
    temp.append(total)
    nums.append(temp)

print(nums)

[[22, 4, 16, 0, 2, 10], [775, 49, 255, 112, 185, 160], [2, 10, 18, 2, 0, 4], [10, 2, 1, 0, 0, 1], [8, 0, 0, 0, 0, 1], [330, 26, 1, 0, 2, 1], [0, 0, 0, 0, 0, 0]]

【讨论】:

  • 嗨,对于 len 1000 的列表,我收到此错误:ValueError: low >= high
  • 你能把你的名单贴出来让我测试一下吗?
  • 问题实际上是您列表中的负值。
  • 你好,我刚刚查过了,没有负值..
  • 完美运行,非常感谢好友的支持 :)
猜你喜欢
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
  • 2017-03-24
  • 1970-01-01
  • 2019-04-16
  • 2015-09-13
  • 2015-12-18
  • 2017-10-01
相关资源
最近更新 更多