2015-01-08 25 views
5

Tôi hiện có ↓ được đặt làm chức năng randprime(p,q). Có cách nào để ngưng tụ điều này, thông qua một cái gì đó như một số điện thoại genexp hoặc listcomp? Đây là chức năng của tôi:Số nguyên tố ngẫu nhiên trong python

n = randint(p, q) 
while not isPrime(n): 
    n = randint(p, q) 
+6

Có vẻ như sẽ tốt hơn khi tạo danh sách các số nguyên tố giữa 'p' và' q' và sau đó chọn một số ngẫu nhiên từ danh sách đó. –

+0

Bạn có thể tăng khả năng số nguyên tố bằng cách đặt bit thấp nhất thành 1, do đó làm cho nó trở thành số lẻ - chỉ có một số nguyên tố, tức là 2. Trên thực tế, tất cả các số nguyên tố không phải là 2 và 3 đều dưới đây hoặc một trên bội số của sáu. –

+1

Tôi ghét khi ai đó downvote một câu hỏi mà không nói lý do tại sao vì OP không thể sửa chữa nó nếu anh ta không biết những gì là sai. –

Trả lời

4

Tốt hơn là chỉ tạo danh sách số nguyên tố, sau đó chọn từ dòng đó. Như vậy, với mã của bạn, cơ hội mỏng sẽ đạt đến vòng lặp vô hạn, nếu không có số nguyên tố trong khoảng thời gian hoặc nếu randint luôn chọn một số nguyên tố thì vòng lặp while sẽ không bao giờ kết thúc.

Vì vậy, đây có lẽ là ngắn hơn và ít rắc rối:

import random 
primes = [i for i in range(p,q) if isPrime(i)] 
n = random.choice(primes) 

Một thuận lợi khác của việc này là không có cơ hội của bế tắc nếu không có số nguyên tố trong khoảng thời gian. Như đã trình bày điều này có thể chậm tùy thuộc vào phạm vi, vì vậy nó sẽ nhanh hơn nếu bạn lưu trữ các số nguyên tố trước thời hạn:

# initialising primes 
minPrime = 0 
maxPrime = 1000 
cached_primes = [i for i in range(minPrime,maxPrime) if isPrime(i)] 

#elsewhere in the code 
import random 
n = random.choice([i for i in cached_primes if p<i<q]) 

Một lần nữa, tối ưu hoá hơn nữa là có thể, nhưng là phụ thuộc rất nhiều vào mã thực tế của bạn .. và bạn biết họ nói gì về sự tối ưu hóa sớm.

+2

Điều này có thể là một ý tưởng rất tồi nếu p và q là thứ tự 10 ** 10, đó là một điều hợp lý để thử nếu bạn đang suy nghĩ về mã hóa. – Joel

+0

Tôi đoán rằng nếu có bất kỳ số nguyên tố giữa 'p' và' q' nó sẽ bế tắc chắc chắn. –

+0

Vâng, có lẽ họ sẽ được bộ nhớ đệm kiểm tra 'isPrime', hoặc có một danh sách dựng sẵn để làm việc. –

-1
next(i for i in itertools.imap(lambda x: random.randint(p,q)|1,itertools.count()) if isPrime(i)) 

Điều này bắt đầu bằng itertools.count() - điều này mang lại một tập hợp vô hạn.

Mỗi số được ánh xạ tới một số ngẫu nhiên mới trong phạm vi, bởi itertools.imap(). imap giống như bản đồ, nhưng trả về một trình lặp, thay vì một danh sách - chúng ta không muốn tạo ra một danh sách các số ngẫu nhiên vô hạn!

Sau đó, tìm thấy số phù hợp đầu tiên và trả về.

Hoạt động hiệu quả, ngay cả khi p và q cách nhau rất xa - ví dụ: 1 và 10 ** 30, tạo danh sách đầy đủ sẽ không hoạt động!

Nhân tiện, điều này không hiệu quả hơn mã của bạn ở trên và khó hiểu hơn rất nhiều - vui lòng xem xét lập trình viên tiếp theo để đọc mã của bạn và chỉ cần làm như bạn đã làm ở trên. Lập trình viên đó có thể là bạn trong sáu tháng, khi bạn quên mã này được cho là phải làm gì!

P.S - trong thực tế, bạn có thể muốn thay thế count() bằng xrange (KHÔNG phạm vi!), Ví dụ: xrange((p-q)**1.5+20) không được nhiều hơn số lần thử (cân bằng giữa các thử nghiệm giới hạn cho phạm vi nhỏ và phạm vi rộng và không có hơn 1/2% cơ hội thất bại nếu thành công), nếu không, như được đề xuất trong một bài đăng khác, bạn có thể lặp lại mãi mãi.

PPS - cải thiện: thay thế random.randint(p,q) với random.randint(p,q)|1 - điều này làm cho mã gấp đôi hiệu quả, nhưng loại trừ khả năng rằng kết quả sẽ là 2.

+0

Tôi coi q-p, và sau đó được đơn giản hóa thành p, và sau đó là' p ** 2'. Câu trả lời mới nhất của tôi (vừa quyết định) là (q-p) ** 2. q-p có lẽ không đủ; Nếu bạn có hai số và một trong số đó là số nguyên tố (ví dụ: q = 18 và p = 19), thì bạn có 25% cơ hội thất bại. Khi phạm vi tăng lên, khả năng bao phủ tất cả các số trong phạm vi giảm (lấy mẫu các số ngẫu nhiên 'phạm vi' trong' dải ô'). –

+0

Đã thực hiện một số hoạt động săn bắn, trường hợp rất xấu là chọn p = 1425172824437699411 và q = p + 1475; trong phạm vi số đó, chỉ có một số nguyên tố (và 1475 số nguyên tố). Mỗi người có một cơ hội 1475/1476 là một phi chính, do đó, ngay cả 1476 cố gắng có 37% cơ hội thất bại. –

+0

Một phép tính khác cho thấy các nỗ lực '(q-p) ** 2' có thể không đủ - cho q = p + 1 (trong đó p hoặc q là số nguyên tố), có 6% cơ hội thất bại cho nhiều thử nghiệm (= 4). Tôi sẽ sửa lại câu trả lời của mình thành '(q-p) ** 2 + 20', sẽ chỉ chậm hơn một chút và làm việc tốt hơn cho các số nhỏ. –

0

Vì vậy, nó sẽ là tuyệt vời nếu bạn có thể sử dụng một iterator để cung cấp cho các số nguyên từ p đến q theo thứ tự ngẫu nhiên (không thay thế). Tôi đã không thể tìm ra cách để làm điều đó. Sau đây sẽ cung cấp cho số nguyên ngẫu nhiên trong phạm vi đó và sẽ bỏ qua bất cứ điều gì mà nó đã được thử nghiệm rồi.

import random 
fail = False 
tested = set([]) 
n = random.randint(p,q) 
while not isPrime(n): 
    tested.add(n) 
    if len(tested) == p-q+1: 
     fail = True 
     break 
    while n in s: 
     n = random.randint(p,q) 

if fail: 
    print 'I failed' 
else: 
    print n, ' is prime' 

Lợi thế lớn của điều này là nếu nói phạm vi bạn đang kiểm tra chỉ là (14,15), mã của bạn sẽ chạy vĩnh viễn.Mã này được đảm bảo để tạo ra một câu trả lời nếu một nguyên tố như vậy tồn tại, và cho bạn biết không có một nếu như một nguyên tố không tồn tại. Bạn rõ ràng có thể làm cho nó nhỏ gọn hơn, nhưng tôi đang cố gắng thể hiện logic.

+0

Có, nhưng tôi sẽ kết thúc nếu đưa ra một phạm vi không có số nguyên tố, và chạy trong thời gian ít hơn đáng kể nếu được cho một phạm vi chỉ với một vài số nguyên tố. – Joel

+3

mã từ OP là 3 dòng nhưng nó sẽ bế tắc nếu không có số nguyên tố giữa p và q để nó không an toàn. –

+0

Đó là tôi, và tôi đã bình chọn bạn vì câu trả lời của bạn, trong khi giới thiệu một cái gì đó hữu ích, là OPPOSITE CHÍNH XÁC của những gì đã được hỏi - 'Có cách nào để ngưng tụ điều này'. Tôi đã cho rằng phần đó không phải của tôi. Nó không phải là cơ sở của câu trả lời của tôi, chỉ là một chú thích. Bạn được hoan nghênh kết hợp mã của tôi vào câu trả lời của bạn dưới dạng chú thích (hoặc ý tưởng từ đó). –

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