简体   繁体   English

生成具有固定和的随机 integer numpy 向量

[英]Generating random integer numpy vector with a fixed sum

Based on the codes, i want to randomize the integer where there are specific range specify but in the last three array I need to have 100 in total.根据代码,我想随机化 integer ,其中指定了特定范围,但在最后三个数组中我总共需要100个。 The sum of the last three array cannot be exceed than 100 .最后三个数组的总和不能超过100 I don't know how to solve this problem.我不知道如何解决这个问题。

self.position = np.array([rd.randint(0,2), rd.randint(0,2), rd.randint(0,100), rd.randint(0,50), rd.randint(0,1)])

Although the solution Rmano suggest is valid, it lack total randomness because once you draw the first random integer the other are pseudo-random or not random at all because of the dependent.尽管Rmano建议的解决方案是有效的,但它缺乏完全随机性,因为一旦你绘制了第一个随机 integer 另一个是伪随机或根本不是随机的,因为依赖。

A more random solution would be, in my opinion:在我看来,一个更随机的解决方案是:

import numpy as np

def generate_fix_sum_random_vec(limit, num_elem, tries=10):
    v = np.random.randint(0, limit, num_elem)
    s = sum(v)
    if (np.sum(np.round(v/s*limit)) == limit):
        return np.round(v / s * limit)
    elif (np.sum(np.floor(v/s*limit)) == limit):
        return np.floor(v / s * limit)
    elif (np.sum(np.ceil(v/s*limit)) == limit):
        return np.ceil(v / s * limit)
    else:
        return generate_fix_sum_random_vec(limit, num_elem, tries-1)



for i in range(25):
    test_vec = generate_fix_sum_random_vec(100, 3)
    test_vec = test_vec.astype(int)
    print("vec: ", test_vec, "sum of vector: ", np.sum(test_vec))

This solution is more robust, and can be valid to any limit on the sum of the vector and it easily applicable to vector in any length by changing the num_elem .该解决方案更健壮,并且可以对向量总和的任何限制有效,并且通过更改num_elem可以轻松应用于任何长度的向量。 Moreover it doesn't assume anything and just trying until it find a match.此外,它不假设任何东西,只是尝试直到找到匹配项。

The output of the loop:循环的output:

vec:  [53 32 15] sum of vector:  100
vec:  [40 38 22] sum of vector:  100
vec:  [56 38  6] sum of vector:  100
vec:  [ 5 17 78] sum of vector:  100
vec:  [12 29 59] sum of vector:  100
vec:  [ 1 34 65] sum of vector:  100
vec:  [ 3 56 41] sum of vector:  100
vec:  [35 65  0] sum of vector:  100
vec:  [54  9 37] sum of vector:  100
vec:  [45  8 47] sum of vector:  100
vec:  [30 56 14] sum of vector:  100
vec:  [34 63  3] sum of vector:  100
vec:  [17 40 43] sum of vector:  100
vec:  [56 36  8] sum of vector:  100
vec:  [52 45  3] sum of vector:  100
vec:  [35 34 31] sum of vector:  100
vec:  [25 41 34] sum of vector:  100
vec:  [ 1 78 21] sum of vector:  100
vec:  [ 1 49 50] sum of vector:  100
vec:  [51 31 18] sum of vector:  100
vec:  [50 10 40] sum of vector:  100
vec:  [36 63  1] sum of vector:  100
vec:  [30 30 40] sum of vector:  100
vec:  [27 30 43] sum of vector:  100
vec:  [21 27 52] sum of vector:  100

There is a need to check that indeed the resulted vector sum to the desired value, because this isn't guaranteed需要检查结果向量是否确实与所需值相加,因为这不能保证

Answer to the comment below from the OP:回答来自 OP 的以下评论:

I am not sure how much randomness you get like this, but:我不确定你会得到多少随机性,但是:

def three_to_100_b():
    a3 = random.randint(0,1)
    a2 = random.randint(0,50)
    a1 = 100-a3-a2
    return a1, a2, a3

will give you three pseudo -random numbers, the first in the range 0-100, the second in the range 0-50, the last one 0 or 1, and summing 100.会给你三个随机数,第一个在 0-100 范围内,第二个在 0-50 范围内,最后一个 0 或 1,总和 100。

But notice that the randomness between a1 and a2 is really small --- they are on a straight line +0 or -1 by definition...但请注意, a1a2之间的随机性非常小——根据定义,它们在一条直线上 +0 或 -1...

在此处输入图像描述

Notice, new answer --- the old one has flaws in randomness.注意,新答案——旧答案在随机性方面存在缺陷。

One method to have three numbers that sum up to 100 is to generate three random numbers, and then scale them so that their sums is 100. This is overly verbose, but the idea is:让三个数字总和为 100 的一种方法是生成三个随机数,然后对它们进行缩放,使它们的总和为 100。这过于冗长,但想法是:

#! /usr/bin/env python3

import random

def three_to_100():
    r1 = random.randint(0,100)
    r2 = random.randint(0,100)
    r3 = random.randint(0,100)
    a1 = r1*100/(r1+r2+r3)
    a2 = r2*100/(r1+r2+r3)
    a3 = 100 - a1 - a2
    return a1, a2,a3

#main
print("x\t y\t z")
for i in range(1000):
    # print(three_to_100())
    a=three_to_100()
    print("{}\t  {}\t {}".format(*a))

I plotted the (x,y) pairs for the first 1000 numbers (the third number is represented by the color of the dot) and I have:我为前 1000 个数字绘制了 (x,y) 对(第三个数字由点的颜色表示),我有:

x,y,z 元组的输出

old answer旧答案

You can generate a number from 0 to 100, then another one from 0 to (100 - the first number), and so on.您可以生成一个从 0 到 100 的数字,然后生成另一个从 0 到(100 - 第一个数字)的数字,依此类推。 The last one won't be random:最后一个不会是随机的:

#! /usr/bin/env python3

import random

def three_to_100():
    r1 = random.randint(0,100)
    r2 = random.randint(0,100-r1)
    r3 = 100 - r1 - r2
    return r1, r2,r3

#main
for i in range(10):
    print(three_to_100())

The output will be: output 将是:

[romano:~/tmp] % ./randsum.py 
(26, 7, 67)
(85, 13, 2)
(43, 41, 16)
(75, 22, 3)
(66, 19, 15)
(30, 16, 54)
(43, 30, 27)
(36, 2, 62)
(31, 2, 67)
(91, 0, 9)

This is a plot of the first two numbers — they seem pretty random, but maybe it's true that they seem a bit crowded on the xy axis.这是前两个数字的 plot - 它们看起来很随机,但也许它们在 xy 轴上看起来有点拥挤是真的。

1000 个数字的分布

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM