简体   繁体   English

生成具有被n整除的随机数列表

[英]Generate list of random number with the sum divisible by n

My concern was what is a good way to generate a list of 10 - 15 numbers that the sum of them always divisible by n. 我关心的是生成10到15个数字列表的好方法,这些数字的总和总是被n整除。

The output should be 输出应为

-8378302799 -8378302799

Here what I got so far, but it not a working script yet. 这是我到目前为止所获得的,但是它还不能正常工作。

import random
import numpy as np

def get_num(x, y, n):
    return [random.choice(range(x, y, n)) if x % n != 0 else random.choice(range(x - (x % n) + n, y, n)) for x in x]


def get_list():
    numb = get_num(0, 9, 2)
    return ''.join(np.random.multinomial(numb, [1/10], size=1))

while True:
    amount = int(input("How many Do you want to generate?" + "\n"))
    for i in range(1,amount):
        get_list()

@Samer Ayoub, answer was what I needed, just added the sep='' so it came as I expected. @Samer Ayoub,答案就是我所需要的,只是添加了sep ='',所以就如我所料。

import random

n, m, k= 3, 9, 14
lis = [random.choice(range(0, m)) for i in range(k)]
tot = sum(lis)
print(*lis, sep = '')

while tot%n != 0:
    tot -= lis.pop()
    last = random.choice(range(0, m))
    lis.append(last)
    tot += last

Perhaps a bit pedantic, but if anyone reading this in the future has a use-case in which questions of probability distribution matters, they should be aware that the algorithm of picking all but the last number at random and then picking the last number so as to satisfy the constraints, introduces a bias in the last number. 也许有点古怪,但是如果将来有人读这个书,有一个概率分布问题很重要的用例,他们应该意识到,随机选择除最后一个数字之外的所有数字,然后选择最后一个数字的算法为了满足约束条件,在最后一个数字中引入了偏差。 As proof of concept: 作为概念证明:

import random, math

def f(k,a,b):
    """generates k random integers in a,b which sum to an even number"""
    start = [random.randint(a,b) for _ in range(k-1)]
    if sum(start) % 2 == 0:
        #pick an even number
        start.append(2*random.randint(math.ceil(a/2),math.floor(b/2)))
    else:
        #pick an off number
        start.append(1 + 2*random.randint(math.ceil((a-1)/2),math.floor((b-1)/2)))
    return start

For example, a typical run of f(3,1,5) produced [1, 5, 2] . 例如,典型的f(3,1,5)运行产生了[1, 5, 2] f(3,1,5) [1, 5, 2]

But: 但:

trials = [f(3,1,5) for _ in range(10000)]
print(sum(trial[0]%2 == 0 for trial in trials)/10000) #percentage of first nums which are even
print(sum(trial[2]%2 == 0 for trial in trials)/10000) #percentage of last nums which are even

typical output: 典型输出:

0.3996
0.5198

Which shows a clear bias. 这显示出明显的偏见。

Generate your list fully, check if the sum is divisible by n, if not replace last element untill it works: 完全生成您的列表,检查总和是否可被n整除,如果不替换最后一个元素,直到它起作用:

import random

n, m, k= 3, 9, 15
lis = [random.choice(range(0, m)) for i in range(k)]
tot = sum(lis)

while tot%n != 0:
    tot -= lis.pop()
    last = random.choice(range(0, m))
    lis.append(last)
    tot += last

An improvement on @SamerAyoub using numpy : 使用numpy对@SamerAyoub的改进:

import numpy as np

n, m, k= 3, 9, 15
arr = np.empty(k, dtype = int)
arr[1:] = np.random.choice(np.arange(0, m), k-1)
rem = arr[1:].sum() % n
arr[0]  = np.random.choice(np.arange(n - rem, m, n))

print(''.join([str(i) for i in arr]))
print(arr.sum()%n == 0)

374564205252063
True

There's also the (not guaranteed to be especially fast, especially if n is large) brute force method, which at least guarantees no bias (but doesn't guarantee ever finishing): 还有一种(不能保证特别快,特别是如果n大的话)蛮力方法,至少可以保证没有偏差(但不保证永远精加工):

def slow_way(n, m, k):
    arr = np.empty(k)
    while arr.sum() % n != 0:
        arr = np.random.choice(np.arange(0, m), k)
    return arr

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

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