快速随机产生0或1

时间:2019-07-01 22:27:16

标签: python

使用python我正在使用random.randint(0,1)随机生成0或1。不过这很慢,因为我需要做大约十亿次。有更快的方法吗?

total=0
n=1000000000
for x in range(n):
    money=2
    while True:
        x=random.randint(0,1)
        if x==1:
            break
        if x==0:
            money*=2
            continue
    total+=money
print(total/n)

5 个答案:

答案 0 :(得分:4)

正如已经评论过的那样,无论如何,在纯Python中这都会有些慢。

但是普通的random.random()(尽管random.randint()是基于[0.0, 1.0)构建的,尽管具有令人惊讶的复杂性)已经返回了0.0到1.0之间的浮点值(或更准确地说,在{{ 1}}),因此,如果您想要一个具有合理稳定分布的随机二进制值,可以执行

from random import random # Avoiding the module attribute access on each loop will save some time
...
if random() < 0.5:
    # do one thing
else:
    # do the other

我认为即使对于1e9循环,这也是可以接受的。否则,您可以尝试使用Cython。

答案 1 :(得分:2)

一种更快的解决方案是使用random.getrandbits(1)

顺便说一句,如果您想知道您的资金循环是否会收敛到特定的值,那就不会。您进行的采样次数越多,平均数字就越高,尽管在每次运行之间差异很大,尤其是在循环次数较少的情况下。

每次迭代都有50%的机会返回2、25%的机会返回4、12.5%的机会返回8,依此类推...

数学上的期望值可以表示为一个序列(不收敛):

∑ 2 * 1/2 + 4 * 1/4 + 8 * 1/8 .... == ∑ 2 ^ p / 2 ^ p == 1 +1 + 1 + ...

换句话说,随着您采样次数的增加,平均值的变化总和会越来越大。

由于您没有进行无数次尝试,因此您将获得实际的数字。上述系列中2(p)的每个幂将平均为1,直到2 ^ p> n。然后,较高功率的期望值将开始下降。

例如,对于2 ^ 30(约1000000000),您将获得前30次2的幂的平均值1。然后,对于2 ^ 31,将得到0.5,对于2 ^ 32,将得到0.25,依此类推。这将在前30个顶部加起来大约为2。因此,理论上,n = 2 ^ 30的平均值应该接近32。

更一般而言,这应该平均为2 + log(n,2),进展并不很快,但 仍将达到无穷大。

例如:

  • 一百万-> log(1000000,2)+2-> 21.9
  • 1亿-> log(100000000,2)+2-> 28.6
  • 10亿-> log(1000000000,2)+2-> 31.9

小样本上会有差异,因为两个高次方的异常值将被随机击中,并对平均值产生重大影响。当样本数量较大时,这些离群值的影响不太明显。

如果您要查找的是一种生成具有指数分布的值的方法,则可能需要尝试random.expovariate()并将其值用作2的指数。

答案 2 :(得分:2)

在Linux上,您可以阅读var patch_size = 37; var NBands = ee.Number(image.bandNames().length()).getInfo(); Export.image.toCloudStorage({ image: image.toArray(), description: outFileName, bucket: 'landsat', scale: scale, region: geometry, fileFormat: 'TFRecord', formatOptions: { patchDimensions: [patch_size, patch_size], tensorDepths: [NBands], compressed: true } });

/dev/urandom

打印(在我的旧笔记本电脑i3-3110上,ubuntu 16.04):

from random import randint, getrandbits, random
from timeit import timeit
from operator import and_
from itertools import starmap

f_in = open('/dev/urandom', 'rb')

def generate_num1(n):
    return starmap(and_, zip(f_in.read(n), [1]*n))

def generate_num2(n):
    return (randint(0, 1) for _ in range(n))

def generate_num3(n):
    return (getrandbits(1) for _ in range(n))

def generate_num4(n):
    return (1 if random() < 0.5 else 0 for _ in range(n))

print(timeit(lambda: list(generate_num1(1024)), number=1000))
print(timeit(lambda: list(generate_num2(1024)), number=1000))
print(timeit(lambda: list(generate_num3(1024)), number=1000))
print(timeit(lambda: list(generate_num4(1024)), number=1000))

这3个选项中的每一个都比0.11714126999140717 1.9653857139928732 0.20527600098284893 0.1918482400069479 快得多。 random.randint似乎最快。

答案 3 :(得分:1)

您可以使用numpy有效地做到这一点。有关numpy随机功能的更多信息,请参见:(link)。这将返回一个numpy数组,并带有结果随机序列。

In [1]: import numpy as np

        np.random.randint(low=0, high=1, size=1000000000)

Out[2]: array([0, 0, 0, ..., 0, 0, 0])

或者,您可以按以下方式使用randbits:

In [1]: from random import getrandbits
        nums = [not random.getrandbits(1) for i in range(0,100000)]

Out[2]: [False,True,...,False]

答案 4 :(得分:0)

这是使用numpy +迭代器的解决方案:

我不确定您的速度如何,但是执行此过程需要6 +/- 0.5秒。

import numpy as np

np.random.seed(11)
n=0
total=0
while n<10**9:
    # 10**5 seems to be the golden number here
    n_vals = np.random.randint(0,2, 10**5)
    n+=10**5

    # The prevalence of zeros shouldn't be diff than that of ones
    n_zeros =  len(n_vals) - np.sum(n_vals)
    # square the value of money
    total += n_zeros*2

print(total/n)
# 1.000063652