如何生成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)。
答案 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