1

我有一个看起来像这样的 for 循环,并且希望让它更快。

我的列表 = 范围(100)

def normalrandom():
    for a in range(100):
        b = random.getrandbits(1)
        if b==1: #do something with mylist[a]

我的列表有大约 100 个元素,而且我知道调用 random 很昂贵。有没有更快的方法来调用 random 并获得 100 个随机布尔值?

编辑:这是迄今为止最好的解决方案。

def fastrandom(): 
    s = list(range(100))
    res = [i for i in s if random.random() >= .5]
    for item in res:
        #do something with mylist[item]
  • 正常随机:0:00:00.591000
  • 快速随机:0:00:00.293000
4

5 回答 5

2

这似乎工作得很好。它返回一个生成器对象,因此唯一的内存使用是n-bit integer r

编辑:不要使用这个!

import random

def rand_bools(n):
    r = random.getrandbits(n)
    return ( bool((r>>i)&1) for i in xrange(n) )

用法:

>>> for b in rand_bools(4): print b
...
False
True
False
True

它通过连续移位r、屏蔽低位并将其转换为bool每次迭代来工作。


编辑:故事的寓意是对您的代码进行基准测试!在得到 Blender 的提示后,我编写了以下测试:

import random
import time

def test_one(N):
    a = 0
    t0 = time.time()
    for i in xrange(N):
        if random.getrandbits(1):  a += 1
    return time.time() - t0

def rand_bools_int_func(n):
    r = random.getrandbits(n)
    return ( bool((r>>i)&1) for i in xrange(n) ) 

def test_generator(gen):
    a = 0
    t0 = time.time()
    for b in gen:
        if b:  a += 1
    return time.time() - t0  

def test(N):
    print 'For N={0}'.format(N)
    print '  getrandbits(1) in for loop              {0} sec'.format(test_one(N))

    gen = ( not random.getrandbits(1) for i in xrange(N) )
    print '  getrandbits(1) generator using not      {0} sec'.format(test_generator(gen))

    gen = ( bool(random.getrandbits(1)) for i in xrange(N))
    print '  getrandbits(1) generator using bool()   {0} sec'.format(test_generator(gen))

    if (N < 10**6):     # Way too slow!
        gen = rand_bools_int_func(N)
        print '  getrandbits(n) with shift/mask          {0} sec'.format(test_generator(gen))

def main():
    for i in xrange(3,8):
       test(10**i)

if __name__ == '__main__':
   main()  

结果:

C:\Users\Jonathon\temp>python randbool.py
For N=1000
  getrandbits(1) in for loop              0.0 sec
  getrandbits(1) generator using not      0.0 sec
  getrandbits(1) generator using bool()   0.0 sec
  getrandbits(n) with shift/mask          0.0 sec
For N=10000
  getrandbits(1) in for loop              0.00200009346008 sec
  getrandbits(1) generator using not      0.00300002098083 sec
  getrandbits(1) generator using bool()   0.00399994850159 sec
  getrandbits(n) with shift/mask          0.0169999599457 sec
For N=100000
  getrandbits(1) in for loop              0.0230000019073 sec
  getrandbits(1) generator using not      0.029000043869 sec
  getrandbits(1) generator using bool()   0.0380001068115 sec
  getrandbits(n) with shift/mask          1.20000004768 sec
For N=1000000
  getrandbits(1) in for loop              0.233999967575 sec
  getrandbits(1) generator using not      0.289999961853 sec
  getrandbits(1) generator using bool()   0.37700009346 sec
For N=10000000
  getrandbits(1) in for loop              2.34899997711 sec
  getrandbits(1) generator using not      2.89400005341 sec
  getrandbits(1) generator using bool()   3.76900005341 sec

总之,我的回答是一个“有趣*的解决方案,但不要使用它!简单地使用它要快得多random.getrandbits(1)

于 2013-08-01T05:27:12.413 回答
0

以下是不同方法的一些时间安排:

代码:

from random import getrandbits, randint, random, sample

s = list(range(100))

def loop_bits():
    res = []
    b = getrandbits(len(s))
    for i in s:
        if b % 2 == 0:
            res.append(i)
        b >>= 1

def comp_bits():
    res = [i for i in s if getrandbits(1)]

def comp_randint():
    res = [i for i in s if randint(0, 1)]

def comp_random():
    res = [i for i in s if random() >= .5]

不同interperter的结果:

$ python2.7 -m timeit -s 'import randtest' 'randtest.loop_bits()'
10000 loops, best of 3: 97.7 usec per loop
$ python2.7 -m timeit -s 'import randtest' 'randtest.comp_bits()'
10000 loops, best of 3: 55.6 usec per loop
$ python2.7 -m timeit -s 'import randtest' 'randtest.comp_randint()'
1000 loops, best of 3: 306 usec per loop
$ python2.7 -m timeit -s 'import randtest' 'randtest.comp_random()'
10000 loops, best of 3: 25.5 usec per loop
$ 
$ pypy -m timeit -s 'import randtest' 'randtest.loop_bits()'
10000 loops, best of 3: 44 usec per loop
$ pypy -m timeit -s 'import randtest' 'randtest.comp_bits()'
10000 loops, best of 3: 41 usec per loop
$ pypy -m timeit -s 'import randtest' 'randtest.comp_randint()'
100000 loops, best of 3: 14.4 usec per loop
$ pypy -m timeit -s 'import randtest' 'randtest.comp_random()'
100000 loops, best of 3: 12.7 usec per loop
$ 
$ python3 -m timeit -s 'import randtest' 'randtest.loop_bits()'
10000 loops, best of 3: 53.7 usec per loop
$ python3 -m timeit -s 'import randtest' 'randtest.comp_bits()'
10000 loops, best of 3: 48.9 usec per loop
$ python3 -m timeit -s 'import randtest' 'randtest.comp_randint()'
1000 loops, best of 3: 436 usec per loop
$ python3 -m timeit -s 'import randtest' 'randtest.comp_random()'
10000 loops, best of 3: 22.2 usec per loop

所以,在所有情况下,最后一个(理解使用random.random()是迄今为止最快的。

于 2013-08-01T06:05:01.910 回答
0

如何生成随机二进制字符串

import random

rand_sequence = [random.randint(0, 1) for x in range(100)]

然后通过索引访问字符串数组

for i in range(len(rand_sequence)):
    if bool(rand_sequence [i]):
        # do something here

或者,您也可以通过 set (0, 1) 生成一串随机整数

rand_sequence = str(bin(random.getrandbits(100)))[2:].zfill(100)
于 2013-08-01T05:31:16.347 回答
0

尝试这个:

mylist = range(100)
todolist= filter(lambda x: random.getrandbits(1),mylist)
todolist
[0, 4, 7, 8, 11, 13, 15, 16, 20, 21, 22, 23, 24, 25, 29, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 52, 53, 54, 56, 59, 64, 67, 68, 70, 71, 80, 81, 82, 85, 89, 90, 93, 95, 96, 97, 99]
len(todolist)
46
for item in todolist : do_work(item)
于 2013-08-01T06:16:02.443 回答
0

只是把这个放在这里让我将来找到......

import random

def random_array(i):
  return [bool(random.getrandbits(1)) for i in range(i)]

用法:

>>> random_array(10)
[False, False, True, True, True, True, True, True, True, False]

>>> random_array(10)
[False, True, True, False, False, True, True, True, False, True]

>>> random_array(10)
[False, True, False, False, True, True, True, True, False, True]
于 2021-07-15T11:32:17.937 回答