仅生成具有特定数字的随机数

时间:2020-07-16 09:21:57

标签: python random

如何从一组特定的数字中生成一个随机数?例如,
我想生成1-100,000范围内的数字,以便每个数字都只有奇数个数字(例如:111135119711等。)

使用我尝试过的随机模块:

import random

rand = random.randint([1, 3, 5, 7, 9]) 

有什么有效的方法吗?
谢谢。

3 个答案:

答案 0 :(得分:5)

一种方法可能是定义要从中进行采样的几率列表,但要记住,对一个数字进行随机采样的可能性有多大。由于2位数字的数量是1位数字的十倍,因此我们需要根据此逻辑设置这些采样大小的权重。

根据这种推理,我们可以使用numpy.random.choice,它允许按照概率分布从列表中进行采样:

from numpy.random import choice

odds = ['1','3','5','7','9']

n_digits = 5 # up to 99999 for ex
range_digits = list(range(1,n_digits))

weights = [5**i for i in range_digits]
weights_sum = sum(weights)
probs = [i/weights_sum for i in weights]

sizes = choice(range_digits,size=n,p=probs)
[int(''.join(choice(odds,size))) for size in sizes]
# [3151, 3333, 1117, 7577, 1955, 1793, 5713, 1595, 5195, 935]

让我们检查为10_000个样本生成的分布:

from collections import Counter

sizes = choice(range_digits,size=10_000,p=probs)
out = [int(''.join(choice(odds,size))) for size in sizes]

Counter(len(str(i)) for i in out)
# Counter({4: 8099, 3: 1534, 2: 304, 1: 63})

答案 1 :(得分:1)

以下是使用列表理解的解决方案:

>>> random.sample([i for i in range(1,100_001) if all([int(x)%2==1 for x in str(i)])], 4)
[3115, 75359, 53159, 31771]

正如下面的注释中指出的那样,数字越大,上述代码的效率就越低,这是因为如果检查了所有数字(如果每个数字仅包含奇数),则它们会变得越来越低效。包括偶数。

如果我们添加另一个过滤器以首先删除所有偶数,则将进行的比较量减少大约三分之一。

这是两者之间的快速比较:

import datetime
import random

def timer(var):
    def wrapper(*args, **kwargs):
        start = datetime.datetime.now()
        result = var()
        print(f"Elapsed time: {datetime.datetime.now()-start}")
        return result
    return wrapper

@timer
def allNumbers():
    return random.sample([i for i in range(1, 1_000_001) if all([int(x) % 2 == 1 for x in str(i)])], 4)

@timer
def oddNumbers():
    return random.sample([i for i in [x for x in range(1, 1_000_001) if x % 2 == 1] if all([int(x) % 2 == 1 for x in str(i)])], 4)

print("Calling allNumbers:")
print(allNumbers())
print("Calling oddNumbers:")
print(oddNumbers())

输出:

Calling allNumbers:
Elapsed time: 0:00:05.119071
[153539, 771197, 199379, 751557]
Calling oddNumbers:
Elapsed time: 0:00:02.978188
[951919, 1399, 199515, 791393]

答案 2 :(得分:0)

给定想要的范围是1-100,000,您将永远不会选择100,000,因为它具有偶数位:0。实际上,最大允许输出为99,999。那是五位数。

您的输出可能有不可见的前导零:允许975,实际上是00975。必须在代码中允许这些前导零。

  1. 选择您有多少个前导零。您范围内数字的10%前导零。其中10%的第二个前导零。其中的10%(千分之一)的第三个零为零,依此类推。五个前导零为0输出。这超出了允许的范围,因此您将需要重新开始拾取。那只会很少发生。

  2. 一旦您知道有多少个前导零,就知道需要多少其他数字。从允许的数字列表中选择很多数字:[1、3、5、7、9]。

相关问题