生成总计为n的随机数

时间:2018-11-15 20:08:05

标签: algorithm random

如何生成1到n个正好等于n的随机数(正整数,大于0)?

如果n = 10,则结果示例:

10
2,5,3
1,1,1,1,1,1,1,1,1,1
1,1,5,1,1,1

每个排列都应具有相同的发生概率,但是,我不需要在数学上精确。因此,如果由于某些模错误而导致概率不同,那么我不在乎。

是否有用于此的算法?我只发现了值个数固定的算法(即给我正好是m个随机数,总和为n)。

2 个答案:

答案 0 :(得分:7)

将数字 n 想象成由n个相等且不可分割的部分组成的行。您的数字是这些部分的总和。您可以在任意两个部分之间剪切原始长度,也可以不剪切。

这意味着有 n-1 个潜在的切入点。

选择一个随机的 n-1 位数字,该数字介于 0 2 ^(n-1)之间;它的二进制表示形式告诉您在哪里切割。

0 : 000 : [-|-|-|-] : 1,1,1,1
1 : 001 : [-|-|- -] :  1,1,2
3 : 011 : [-|- - -] :   1,3
5 : 101 : [- -|- -] :   2,2
7 : 111 : [- - - -] :    4


在python-3中实现

import random


def perm(n, np):
    p = []
    d = 1
    for i in range(n):
        if np % 2 == 0:
            p.append(d)
            d = 1
        else:
            d += 1
        np //= 2
    return p


def test(ex_n):
    for ex_p in range(2 ** (ex_n - 1)):
        p = perm(ex_n, ex_p)
        print(len(p), p)


def randperm(n):
    np = random.randint(0, 2 ** (n - 1))
    return perm(n, np)

print(randperm(10))

您可以通过为 n

生成所有可能的解决方案来进行验证
test(4)

输出:

4 [1, 1, 1, 1]
3 [2, 1, 1]
3 [1, 2, 1]
2 [3, 1]
3 [1, 1, 2]
2 [2, 2]
2 [1, 3]
1 [4]

答案 1 :(得分:0)

使用模。

这应该让您过得开心

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    srand(time(0));
    int n=10;
    int x=0; /* sum of previous random number */
    while (x<n) {
                int r = rand() % (n-x) + 1;
                printf("%d ", r);
                x += r;
    }
    /* done */
    printf("\n");
}

示例输出:

10
1 1 8 
3 4 1 1 1 
6 3 1 
9 1 
6 1 1 1 1 
5 4 1