2017-10-18 165 views
2

我想在Python中生成1或-1,作为在非负数和非正数之间随机化或随机更改已存在整数的符号的步骤。在Python中生成1或-1的最佳方法是什么?假设均匀分布的,我知道我可以使用:随机生成1或-1(正整数或负整数)

import random 

#method1 
my_number = random.choice((-1, 1)) 

#method2 
my_number = (-1)**random.randrange(2) 

#method3 
# if I understand correctly random.random() should never return exactly 1 
# so I use "<", not "<=" 
if random.random() < 0.5: 
    my_number = 1 
else: 
    my_number = -1 

#method4 
my_number = random.randint(0,1)*2-1 

使用timeit模块,我得到了以下结果:

#method1 
s = "my_number = random.choice((-1, 1))" 
timeit.timeit(stmt = s, setup = "import random") 
>2.814896769857569 
#method2 
s = "my_number = (-1)**random.randrange(2)" 
timeit.timeit(stmt = s, setup = "import random") 
>3.521280517518562 
#method3 
s = """ 
if random.random() < 0.5: my_number = 1 
else: my_number = -1""" 
timeit.timeit(stmt = s, setup = "import random") 
>0.25321546903273884 
#method4 
s = "random.randint(0,1)*2-1" 
timeit.timeit(stmt = s, setup = "import random") 
>4.526625442240402 

如此出人意料方法3是最快的。我打赌方法1是最快的,因为它也是最短的。另外方法1(因为Python 3.6我认为?)和3给出了引入不均匀分布的可能性。虽然方法1是最短的(主要advantege)现在我会选择方法3:在Python

s = """ 
import random 
def positive_or_negative(): 
    if random.random() < 0.5: 
     return 1 
    else: 
     return -1 
     """ 
timeit.timeit(stmt = "my_number = positive_or_negative()", setup = s) 
>0.3916183138621818 

没有更好的(更快或更短)方法随机生成-​​1或1:

def positive_or_negative(): 
    if random.random() < 0.5: 
     return 1 
    else: 
     return -1 

测试?任何原因为什么你会选择方法1而不是方法3,反之亦然?

+2

方法3是最快的,因为所有其他方法都必须在内部执行类似的操作。 – Barmar

回答

2

的一个班轮变化#3:

return 1 if random.random() < 0.5 else -1 

它比'数学'变种更快(er),因为它不涉及额外的算术。

-4

我的代码

vals = array("i", [-1, 1]) 

def my_rnd(): 
    return vals[randint(0, 7) % 2] 
+1

你是否声称这更快?为什么使用'array.array'? –

+1

为什么使用'randint(0,7)%2'而不是'randint(0,1)'? – Barmar

+0

我的测试显示这比所有OP的选项都要慢。 – RobertB

0

生成,如果你打算做很多,其中通过使用numpy的随机数的最快方法:

In [1]: import numpy as np 

In [2]: import random 

In [3]: %timeit [random.choice([-1,1]) for i in range(100000)] 
10 loops, best of 3: 88.9 ms per loop 

In [4]: %timeit [(-1)**random.randrange(2) for i in range(100000)] 
10 loops, best of 3: 110 ms per loop 

In [5]: %timeit [1 if random.random() < 0.5 else -1 for i in range(100000)] 
100 loops, best of 3: 18.4 ms per loop 

In [6]: %timeit [random.randint(0,1)*2-1 for i in range(100000)] 
1 loop, best of 3: 180 ms per loop 

In [7]: %timeit np.random.choice([-1,1],size=100000) 
1000 loops, best of 3: 1.52 ms per loop 
+0

至少最后一个不仅返回-1,+ 1。 –

+0

是不是最后一个(7)相当于'random.choices([ - 1,1],k = 100000)'在'random'模块中? – Siemkowski

+0

@Siemkowski有一个编辑,上面的评论提到(8)我想。 – sascha

2

这里还有一个班轮,我的时机展示给比的if/else比较0.5速度更快:

[-1,1][random.randrange(2)] 
+0

我测试了这个 - 它不是更快。 'timeit.timeit(stmt =“my_number = 1 if random.random()<0.5 else -1”,setup =“import random”)''> 0.17129717730503558'和'timeit.timeit(“my_number = [-1,1 ] [random.randrange(1,2)]“,setup =”import random“)''> 2.5639535604734647' – Siemkowski

+0

@Siemkowski您的范围指定与我的不同,并且各种版本的Python之间可能存在差异。 – pjs

+0

对不起,贴错线,但对我来说还是比较慢。我使用'Python 3.6.1'。你测试了什么版本? – Siemkowski

1

如果需要单位(每个呼叫一个),你已经做了你的基准和其他答案提供了更多信息。

如果您需要很多位或可以预先计算位阵列供以后使用,numpy的方法可能闪耀。

下面是使用numpy的(这令人惊讶的没有一个专门用于这项工作正是法)一些演示的方法

import numpy as np 
import random 

def sample_bits(N): 
    assert N % 8 == 0 # demo only 
    n_bytes = N // 8 

    rbytes = np.random.randint(0, 255, dtype=np.uint8, size=n_bytes) 
    return np.unpackbits(rbytes) 

def alt(N): 
    return np.random.choice([-1,1],size=N) 

def alt2(N): 
    return [1 if random.random() < 0.5 else -1 for i in range(N)] 

if __name__ == '__main__': 
    import timeit 
    print(timeit.timeit("sample_bits(1024)", setup="from __main__ import sample_bits", number=10000)) 
    print(timeit.timeit("alt(1024)", setup="from __main__ import alt", number=10000)) 
    print(timeit.timeit("alt2(1024)", setup="from __main__ import alt2", number=10000)) 

输出:

0.06640421246836543 
0.352129537507486 
1.5522800431775592 

的总体思路是:

  • 使用numpy在一个步骤中生成许多uint8
    • (有可能是一个更好的利用内部功能,而randint-API)
  • 解压UINT8的8位
    • 从randint的均匀度均匀性担保如下

再次,这只是一个演示:

  • 为一个特定的情况下
  • 不关心不同的结果类型的这些功能
  • 不关心-1对0(可能是您的使用情况很重要)
  • (即使不是最优的比较到更低级别的方法;内部使用的MT可以用作比特源,与其他许多PRNG不同,它不需要fp数学)