2010-12-28 4 views
7

पायथन में संख्याओं की प्राथमिकता की जांच करने के लिए मेरा वर्तमान एल्गोरिदम 10 मिलियन से 1 अरब के बीच की संख्या को धीमा करने का तरीका है। मैं यह जानना चाहता हूं कि मुझे कभी भी 1 अरब से अधिक संख्याएं नहीं मिलेंगी।जल्दी से निर्धारित करें कि संख्याओं के लिए पायथन में कोई संख्या प्रमुख है <1 अरब

संदर्भ यह है कि मुझे प्रोजेक्ट यूलर की समस्या 60 को हल करने के लिए पर्याप्त कार्यान्वयन नहीं मिल सकता है: मुझे 75 सेकंड में समस्या का उत्तर मिल रहा है जहां मुझे इसे 60 सेकंड में चाहिए। http://projecteuler.net/index.php?section=problems&id=60

मेरे पास मेरे निपटारे में बहुत कम स्मृति है इसलिए मैं 1 अरब से नीचे के सभी प्राइम नंबरों को स्टोर नहीं कर सकता।

मैं वर्तमान में 6k ± 1 के साथ ट्यून किए गए मानक परीक्षण प्रभाग का उपयोग कर रहा हूं। क्या इससे कुछ बेहतर है? क्या मुझे पहले से ही संख्याओं के लिए राबिन-मिलर विधि प्राप्त करने की आवश्यकता है जो इस बड़े हैं।

primes_under_100 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] 
def isprime(n): 
    if n <= 100: 
     return n in primes_under_100 
    if n % 2 == 0 or n % 3 == 0: 
     return False 

    for f in range(5, int(n ** .5), 6): 
     if n % f == 0 or n % (f + 2) == 0: 
      return False 
    return True 

मैं इस एल्गोरिदम को कैसे सुधार सकता हूं?

प्रेसिजन: मैं अजगर के लिए नया हूं और केवल पाइथन 3+ के साथ काम करना चाहता हूं।


अंतिम कोड

जो लोग रुचि रखते हैं, MAK के विचारों का उपयोग कर के लिए, मैं निम्नलिखित कोड तेज है जो 1/3 के बारे में उत्पन्न, मुझे भी कम समय में यूलर समस्या के परिणाम प्राप्त करने के लिए अनुमति देता है 60 सेकंड से अधिक!

from bisect import bisect_left 
# sqrt(1000000000) = 31622 
__primes = sieve(31622) 
def is_prime(n): 
    # if prime is already in the list, just pick it 
    if n <= 31622: 
     i = bisect_left(__primes, n) 
     return i != len(__primes) and __primes[i] == n 
    # Divide by each known prime 
    limit = int(n ** .5) 
    for p in __primes: 
     if p > limit: return True 
     if n % p == 0: return False 
    # fall back on trial division if n > 1 billion 
    for f in range(31627, limit, 6): # 31627 is the next prime 
     if n % f == 0 or n % (f + 4) == 0: 
      return False 
    return True 
+0

यह Py3k ??? – st0le

+0

मुझे इसे पायथन 3 या पायथन 3.1 नाम से पता था, लेकिन ऐसा लगता है कि Py3k इन संस्करणों का संदर्भ देता है। –

+0

यह 'f' और' f + 4' नहीं होना चाहिए ... क्या आप पुष्टि कर सकते हैं? क्यों '4'? – st0le

उत्तर

11

10^9 जितना बड़ा संख्या के लिए, एक दृष्टिकोण एसकर्ट (10^9) तक सभी प्राइम उत्पन्न करने के लिए हो सकता है और फिर उस सूची में संख्याओं के विरुद्ध इनपुट नंबर की विभाज्यता की जांच कर सकता है। यदि कोई संख्या किसी अन्य प्राइम द्वारा अपने वर्ग रूट से कम या उसके बराबर विभाजित नहीं है, तो यह स्वयं ही एक प्राइम होना चाहिए (इसमें कम से कम एक कारक < = sqrt और अन्य> = sqrt प्रधान नहीं होना चाहिए)। ध्यान दें कि आपको सभी संख्याओं के लिए विभाज्यता की जांच करने की आवश्यकता नहीं है, केवल वर्ग रूट तक (जो लगभग 32,000 है - मुझे लगता है कि काफी प्रबंधनीय है)। आप sieve का उपयोग करके प्राइम की सूची जेनरेट कर सकते हैं।

आप probabilistic prime test के लिए भी जा सकते हैं। लेकिन उन्हें समझना मुश्किल हो सकता है, और इस समस्या के लिए केवल प्राइम की जेनरेट की गई सूची का उपयोग करना पर्याप्त होना चाहिए।

+0

में बस रेंज बन गया हां, 32k संख्या वास्तव में कुछ मैं स्टोर कर सकता हूं। अछा सुझाव। –

+2

@ फ़ोर, यदि संख्या 32k से कम है, तो बाइनरी खोज का उपयोग करें। 'bisect' मॉड्यूल का उपयोग कर। – st0le

1

आपको पहले अपने n केवल अपने primes_under_100 द्वारा विभाजित कर सकते हैं।

इसके अलावा, अधिक प्राइम प्रीकंप्यूट करें।

इसके अलावा, आप वास्तव में स्मृति में range() परिणाम संग्रहीत करते हैं - irange() का उपयोग करें और Sieve of Eratosthenes algorithm चलाने के लिए इस मेमोरी का उपयोग करें।

+0

आपका मतलब है 'xrange'। – st0le

+0

ठीक है, मैं स्मृति में छोटा नहीं हूं;) और मैं अजगर का उपयोग कर रहा हूं 3. मैंने कभी भी अजगर में xrange नहीं देखा 3. –

+0

@ st0le हाँ, ज़ाहिर है। – crazylammer

3

प्रोजेक्ट यूलर समस्याओं को हल करने के लिए मैंने आपके प्रश्न में जो सुझाव दिया है: Miller Rabin परीक्षण (सी # में लागू करें) लेकिन मुझे संदेह है कि यह पाइथन में तेज़ होगा)। एल्गोरिदम इतना मुश्किल नहीं है। 4,75 9, 123,141 से नीचे की संख्या के लिए यह जांचने के लिए पर्याप्त है कि संख्या 2, 7, 61 के आधार पर एक मजबूत छद्म प्राइम है। छोटे प्राइम द्वारा परीक्षण विभाजन के साथ संयोजन करें।

मुझे नहीं पता कि आपने कितनी समस्याओं का समाधान किया है, लेकिन आपके निपटान में तेज़ प्रारंभिक परीक्षण होने से कई समस्याओं के लिए बहुत महत्वपूर्ण मूल्य होगा।

+0

ठीक है, उस मामले में, आप छोटे प्राइम्स को क्या कहते हैं? मुझे क्या सीमा तय करनी चाहिए? –

+0

@ फ्रोर: आपको इष्टतम मूल्य खोजने के लिए प्रयोग करना होगा, लेकिन मैं 100 से नीचे के सभी प्राइम्स को आजमाकर शुरू कर दूंगा। आईआईआरसी यह भी हो सकता है कि मैंने आधारों को छोड़कर सभी मूल्यों के लिए ट्रायल डिवीजन को समाप्त कर दिया (इस मामले में 2, 7, 61)। –

+0

[पायथन: बड़े एन तक सही साबित हुआ] (https://rosettacode.org/wiki/Miller%E2%80%93Rabin_primality_test#Python:_Proved_correct_up_to_large_N) –

संबंधित मुद्दे