在一个范围内生成N个正整数,在python中累加总数

时间:2016-10-25 03:53:22

标签: python python-2.7 numpy random range

我见过其他帖子解决类似问题。我知道如何生成N个正整数。我也知道如何限制随机生成的整数之和。唯一的问题是满足N值中没有一个超出指定范围的条件。

e.g。 generate_ints(n, total, low, high)应生成n值数组,以使每个值介于低和高之间,并且总和加起来为总和。任何指针/帮助将不胜感激。

例如。generate_ints(4, 40, 4, 15)应生成类似

的内容
[7,10,13,10]

我不在乎这些数字是否重复,只要它们没有高度倾斜。我正在使用np.randon.randint(5,15,n)来选择整数。

到目前为止,我已经尝试过以下方法,但它不起作用 -

import numpy as np 
import random 
from random import uniform as rand 

total=50 
n=10 
low=2 
high=15 
result=[] 
m=0 
nobs=1 
while nobs <= n: 
    if m >= (total - low): 
        last_num= total -new_tot 
        result.append(last_num) 
    else: 
        next_num=np.random.randint(low,high,1) 
        new_tot = sum(result) + next_num 
        result.append(next_num) 
        m=new_tot 
    nobs +=1 

print result 
print sum(result)

再次感谢。

3 个答案:

答案 0 :(得分:1)

$(document).ready(function() {

  $('#button').on('click', function(e) {
    var episode = Number($("#input").val());
    $('#counter').val(episode);
    var vid = document.getElementById('vid1');
    vid.src = 'http://glpjt.s3.amazonaws.com/so/av/vid' + episode + '.mp4';
    vid.load();
    vid.play();

  });
});

结果:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<fieldset>
  <legend>Video Episode:
    <output id='counter'></output>
  </legend>
  <input type="number" value="Episode Number" id="input" style='width:4ex' min='1' max='5'>
  <button type="button" class='btn' id="button">Watch</button>
</fieldset>

<video id="vid1" class="vid" style='width: 90vw;' controls>
  <source src="http://glpjt.s3.amazonaws.com/so/av/vid1.mp4" type='video/mp4'>
</video>

答案 1 :(得分:0)

这是我将要解释的尝试。

import numpy as np


def generate_ints(n, total, low, high):
    begin = 0
    randys = []
    correctTotal = False
    while correctTotal is False:
        while begin < n:
            r1 = np.random.randint(low, high, 1)
            randys.append(r1)
            begin += 1
        if sum(randys) == total:
            correctTotal = True
        else:
            begin = 0
            del randys[:]
    generated_list = np.array(randys).tolist()
    gen = [g[0] for g in generated_list]
    return gen


my_list = generate_ints(4, 40, 4, 15)
print "Generated list '{}' with sum {}.".format(my_list, sum(my_list))

在函数内部,我设置了两个常量randysbegin。在内部while循环中,只要begin小于n,它就会在nlow之间生成high个随机整数。如果总和等于total,则退出外部while循环,否则需要重置常量。

只需返回randys即可获得NumPy array的列表。使用tolist()方法,这会产生一个列表。

现在我们有了一个列表清单。我用简短的列表理解将它弄平了。最后return根据需要列出并输出。

HTH。

答案 2 :(得分:0)

如果我正确理解规范,您希望随机生成受限整数compositions,以便每个可能的组合具有相同的被选择的可能性。

我们可以使this answer适应均匀生成随机整数partition的问题,以便针对小输入值精确地解决此问题。我们只需要一种计算受限制的k-成分的方法。在数学this answer中有一个关于相关问题的递归公式,但事实证明,作为this answer的一部分提到的使用二项式系数的公式更明确。这是纯Python中的一个实现:

import functools
import random

@functools.lru_cache(1 << 10)
def C1(n, k, a, b):
    "Counts the compositions of `n` into `k` parts bounded by `a` and `b`" 
    return C2(n - k*(a - 1), k, b - (a - 1))

def C2(n, k, b):
    "Computes C(n, k, 1, b) using binomial coefficients"
    total = 0
    sign = +1

    for i in range(0, k + 1):
        total += sign * choose(k, i) * choose(n - i*b - 1, k - 1)
        sign = -sign

    return total

def choose(n, k):
    "Computes the binomial coefficient of (n, k)"
    if k < 0 or k > n:
        return 0

    if k == 0 or k == n:
        return 1

    k = min(k, n - k)
    c = 1

    for i in range(k):
        c = c * (n - i) // (i + 1)

    return c

def check_pre_and_post_conditions(f):
    def wrapper(n, k, a, b):
        assert 1 <= k <= n, (n, k)
        assert 1 <= a <= b <= n, (n, a, b)
        assert k*a <= n <= k*b, (n, k, a, b)

        comp = f(n, k, a, b)

        assert len(comp) == k, (len(comp), k, comp)
        assert sum(comp) == n, (sum(comp), n, comp)
        assert all(a <= x <= b for x in comp), (a, b, comp)

        return comp
    return functools.wraps(f)(wrapper)

@check_pre_and_post_conditions
def random_restricted_composition(n, k, a, b):
    "Produces a random composition of `n` into `k` parts bounded by `a` and `b`"
    total = C1(n, k, a, b)
    which = random.randrange(total)
    comp = []

    while k:
        for x in range(a, min(b, n) + 1):
            count = C1(n - x, k - 1, a, b)

            if count > which:
                break

            which -= count

        comp.append(x)
        n -= x
        k -= 1

    return comp

要选择随机组合,我们只需生成一个小于可能组合总数的随机索引,然后构建i-th词典组成(请参阅链接问题以解释所使用的递归关系)。这应该以相同的概率产生所有可能的结果。

但是,因为C1(n, k, a, b)呈指数级增长,对于nk的大值,此方法相当慢。对于较大的值,近似解决方案将为您提供更好的服务。

相关问题