簡體   English   中英

如何生成隨機數列表,使它們的總和等於隨機選擇的數

[英]How to generate a list of random numbers so their sum would be equal to a randomly chosen number

我想生成一個隨機分布的數字列表,以便它們的總和等於隨機選擇的數字。 例如,如果隨機選擇的數字是 5,則分布將是 [1 2 2] 或 [2 3] 或 [1 1 1 2] 等等。 歡迎任何建議!

n是您希望值相加的數字。 生成隨機大小(小於n )的隨機sample ,由 1 到n范圍內的值組成,不包括n 現在添加端點 0 和n ,然后排序。 排序值的連續差值的總和為n

import random as r

def random_sum_to(n):
    a = r.sample(range(1, n), r.randint(1, n-1)) + [0, n]
    list.sort(a)
    return [a[i+1] - a[i] for i in range(len(a) - 1)]

print(random_sum_to(20))  # yields, e.g., [4, 1, 1, 2, 4, 2, 2, 4]

如果您希望能夠明確指定總和中的項數,或者如果未指定則使其是隨機的,請添加一個可選參數:

import random as r

def random_sum_to(n, num_terms = None):
    num_terms = (num_terms or r.randint(2, n)) - 1
    a = r.sample(range(1, n), num_terms) + [0, n]
    list.sort(a)
    return [a[i+1] - a[i] for i in range(len(a) - 1)]

print(random_sum_to(20, 3))   # [9, 7, 4] for example
print(random_sum_to(5))       # [1, 1, 2, 1] for example

在循環中,您可以繼續在 1 和剩余總和之間繪制一個隨機數,直到達到總數

from random import randint
def generate_values(n):
    values = []
    while n > 0:
        value = randint(1, n)
        values.append(value)
        n -= value
    return values

此類函數的一些示例

>>> generate_values(20)
[17, 1, 1, 1]
>>> generate_values(20)
[10, 4, 4, 1, 1]
>>> generate_values(20)
[14, 4, 1, 1]
>>> generate_values(20)
[5, 2, 4, 1, 5, 1, 1, 1]
>>> generate_values(20)
[2, 13, 5]
>>> generate_values(20)
[14, 3, 2, 1]

考慮先連續做。 暫時我們不關心最終數字,所以讓我們在區間 [0...1] 中均勻采樣 X_i,使它們的總和等於 1

X_1 + X_2 + ... X_n = 1

這是眾所周知的分布,稱為狄利克雷分布,或伽馬變量,或單純形采樣。 請參閱生成總和為 M 的 N 個統一隨機數的詳細信息和討論。 可以使用random.gammavariate(a,1)或正確處理角點 gamma 變量,參數為 1 是等效指數分布,直接采樣代碼如下

def simplex_sampling(n):
    r = []
    sum = 0.0
    for k in range(0,n):
        x = random.random()
        if x == 0.0:
            return (1.0, make_corner_sample(n, k))

        t = -math.log(x)
        r.append(t)
        sum += t

    return (sum, r)

def make_corner_sample(n, k):
    r = []
    for i in range(0, n):
       if i == k:
           r.append(1.0)
       else:
           r.append(0.0)

    return r

所以從simplex_sampling你有向量和要用作歸一化的總和。

因此,將其用於,例如,N=5

N = 5

sum, r = simplex_sampling(N)

norm = float(N)/sum

# normalization together with matching back to integers
result = []
for k in range(N):
    # t is now float uniformly distributed in [0.0...N], with sum equal to N
    t = r[k] * norm 
    # not sure if you could have zeros,
    # and check for boundaries might be useful, but
    # conversion to integers is trivial anyway:
    # values in [0...1) shall be converted to 0,
    # values in [1...2) shall be converted to 1, etc
    result.append( int(t) )

這是一個簡單的方法,一個隨機的概率列表,其中總和等於 1;

a = np.random.random(2)
a /=sum(a)
a

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM