2015-04-11 14 views
10

Tôi muốn chọn một số nguyên ngẫu nhiên giữa ab, bao gồm.Hiệu suất của sự lựa chọn so với randint

Tôi biết 3 cách để thực hiện. Tuy nhiên, hiệu suất của họ có vẻ rất phản trực giác:

import timeit 

t1 = timeit.timeit("n=random.randint(0, 2)", setup="import random", number=100000) 
t2 = timeit.timeit("n=random.choice([0, 1, 2])", setup="import random", number=100000) 
t3 = timeit.timeit("n=random.choice(ar)", setup="import random; ar = [0, 1, 2]", number=100000) 

[print(t) for t in [t1, t2, t3]] 

Trên máy tính của tôi, điều này mang lại:

0.29744589625620965 
0.19716156798482648 
0.17500512311108346 

Sử dụng một online interpreter, điều này mang lại:

0.23830216699570883 
0.16536146598809864 
0.15081614299560897 

Lưu ý cách trực tiếp nhất phiên bản (# 1) sử dụng chức năng chuyên dụng để thực hiện những gì tôi đang làm là 50% tồi tệ hơn rằng phiên bản kỳ lạ nhất (# 3) được xác định trước một mảng và sau đó chọn ngẫu nhiên từ đó.

Điều gì đang xảy ra?

+0

Thử so sánh t1, t2 và t3 với 'lựa chọn (phạm vi (3))' và câu trả lời phải rõ ràng. – Shashank

+0

't2' và' t3' giống nhau, nhưng trong 't2' bạn đo việc tạo danh sách và trong' t3' bạn không làm. – Jens

+0

@ Jens Vâng, 't2' có liên quan nếu bạn định tạo một vài số cùng một lúc,' t3' tiết kiệm thời gian trong trường hợp bạn biết bạn sẽ cần nhiều số. – Superbest

Trả lời

5

Chỉ là chi tiết triển khai. randint đại biểu đến randrange, do đó, nó có một lớp gọi điện trên cao chức năng khác và randrange trải qua rất nhiều kiểm tra đối số và các tranh chấp khác. Ngược lại, choice thực sự là một lớp lót đơn giản.

Đây là con đường mã randint đi qua cho cuộc gọi này, với ý kiến ​​và mã chưa thi hành tước ra:

def randint(self, a, b): 
    return self.randrange(a, b+1) 

def randrange(self, start, stop=None, step=1, _int=int, _maxwidth=1L<<BPF): 
    istart = _int(start) 
    if istart != start: 
     # not executed 
    if stop is None: 
     # not executed 

    istop = _int(stop) 
    if istop != stop: 
     # not executed 
    width = istop - istart 
    if step == 1 and width > 0: 
     if width >= _maxwidth: 
      # not executed 
     return _int(istart + _int(self.random()*width)) 

Và đây là đường dẫn mã choice đi qua:

def choice(self, seq): 
    return seq[int(self.random() * len(seq))] 
+2

Cũng lưu ý rằng, đối với cả hai, sự khác biệt có vẻ không đổi. Sử dụng 'range (10000)' thay vì '[0, 1, 2]' và làm 'randint (0, 10000)' về cơ bản cũng giống như trong ví dụ nhỏ. Vì vậy, về cơ bản các chi phí bạn mô tả chỉ làm cho 'randint' 0,00012 giây chậm hơn cho mỗi cuộc gọi hơn' lựa chọn' (giả sử bạn có thể xác định trước bộ lựa chọn của bạn). Đây không phải là vấn đề lớn. 't2', tuy nhiên, nên tránh, vì nó cũng là thời gian tạo ra danh sách, và vì vậy nó sẽ trở nên chậm với danh sách lớn. – BrenBarn

+0

@BrenBarn Bạn có thể tránh các chi phí tạo ra nếu bạn chỉ cần sử dụng một tuple. – Veedrac

Các vấn đề liên quan