2010-06-15 17 views
11

मैं गणित मॉड्यूल का उपयोग किये बिना किसी संख्या का वर्ग रूट खोजना चाहता हूं, क्योंकि मुझे फ़ंक्शन को कुछ 20k बार कॉल करने की आवश्यकता है और जब भी फ़ंक्शन कोगणित मॉड्यूल का उपयोग किए बिना वर्ग रूट कैसे करें?

कहा जाता है तो मैथ मॉड्यूल से लिंक करके निष्पादन को धीमा करना नहीं चाहता

क्या वर्ग रूट खोजने के लिए कोई तेज़ और आसान तरीका है?

+3

sqrt() एस धीमा है। क्या आपको वास्तव में 20k विशिष्ट जड़ें खोजने की ज़रूरत है, या आप लुकअप टेबल या कैश परिणामों का उपयोग कर सकते हैं? –

उत्तर

24

गणित मॉड्यूल आयात करना केवल एक बार होता है, और संभवतः आप गणित मॉड्यूल से अधिक तेज़ नहीं होंगे। Which is faster in Python: x**.5 or math.sqrt(x)? के संबंध में एक पुराना स्टैक ओवरफ्लो प्रश्न भी है। यह स्पष्ट नहीं है कि कौन सी विधि तेज है।

शायद NumPy और SciPy पर एक नज़र डालें, अनिवार्य रूप से sqrt के लिए नहीं, लेकिन यदि आप कुछ भारी गणना कर रहे हैं तो वे आसान हो सकते हैं।

+8

+1 दोनों प्रश्नों के उत्तर देने के लिए +1 और वास्तव में उत्तर देने वाले प्रश्न का उत्तर देने के लिए +1! – Skeolan

+4

बस इतना ही पता है कि, एक नम्पी सरणी का उपयोग करके और पूरी सरणी को .5 शक्ति तक बढ़ाकर 20k वर्ग की जड़ें कम से कम 60x के कारक द्वारा एक ही numpy सरणी पर फिर से चलने पर मेरे परीक्षण में। –

+0

मैक ओएस एक्स पर पायथन 2.6.5 के साथ, 'sqrt()' वास्तव में तेज़ है (मेरा जवाब देखें)। दोनों दृष्टिकोण वास्तव में अलग हैं, और जो तेजी से कार्यान्वयन विवरण पर निर्भर करता है। – EOL

3

आप न्यूटन की विधि को कार्यान्वित कर सकते हैं, हालांकि, यह वास्तव में तेज़ है, लेकिन सी संस्करण से तेज़ होने की संभावना नहीं है जो मुझे लगता है कि गणित मॉड्यूल में लागू किया गया है। http://en.wikipedia.org/wiki/Methods_of_computing_square_roots देखें।

3

उपयोग बिजली ऑपरेटर, और 1/2 सत्ता में अपनी संख्या बढ़ा:

>>> 2**0.5 
1.4142135623730951 

चाहे वह तेज है के रूप में:

>>> timeit.timeit(stmt='sqrt(x)', setup='from math import sqrt; x = 2') 
0.7182440785071833 
>>> timeit.timeit(stmt='x**0.5', setup='from math import sqrt; x = 2') 
0.87514279049432275 
+0

मुझे अपने कंप्यूटर पर समान परिणाम मिलते हैं, लेकिन जब मैं लिंक किए गए प्रश्न के स्वीकृत उत्तर से बेंचमार्क आज़माता हूं, तो math.sqrt तेज़ होता है। यहां कुछ मजाकिया चल रहा है। –

+0

ये समय परीक्षण बहुत प्रतिनिधि नहीं हैं: आप मेरा जवाब देख सकते हैं, जो दिखाता है कि '** 0.5' वास्तव में 'math.sqrt' से धीमा है। कारण यह है कि '2 ** 0.5' एक पूर्व-गणना संख्यात्मक स्थिर है। – EOL

+0

@EOL - मुझे अन्य नंबरों के साथ समान परिणाम मिलते हैं (यानी, '0.42521 ** 0.5'' sqrt (0.42521) 'से लगभग 7 गुना तेज है। मैं कोई निष्कर्ष नहीं बना रहा हूं, लेकिन परीक्षण मेरे लिए मान्य लगता है। – Seth

10

के रूप में फेबियन ने कहा, यह तेजी से होने के लिए मुश्किल है math.sqrt। इसका कारण यह है कि यह सी लाइब्रेरी से सीपी लाइथ से संबंधित फ़ंक्शन को कॉल करता है।

from math import sqrt 

sqrt के बाद के प्रत्येक कॉल नहीं है इसे गणित मॉड्यूल है, जो निष्पादन समय की बचत होती है में देखने के लिए होगा:

हालांकि, अगर आप चीजों विशेषता देखने की भूमि के ऊपर निकाल कर में तेजी लाने के कर सकते हैं:

print sqrt(2) 

यहाँ धीमी करने के लिए संख्या के समय कर रहे हैं सबसे तेजी से, (पायथन 2.6.5, मैक ओएस एक्स 10.6.3): sqrt**0.5 की तुलना में तेजी है:

[email protected] ~ % python -m timeit -s 'from math import sqrt; x = 2' 'sqrt(x)' 
1000000 loops, best of 3: 0.207 usec per loop 
[email protected] ~ % python -m timeit -s 'x = 2' 'x**0.5' 
1000000 loops, best of 3: 0.226 usec per loop 
[email protected] ~ % python -m timeit -s 'import math; x = 2' 'math.sqrt(x)' 
1000000 loops, best of 3: 0.268 usec per loop 

ध्यान दें कि समय परीक्षण परिवर्तनीय के वर्ग रूट की गणना करता है। वे 2**0.5 की तरह एक निरंतर गणना नहीं है, क्योंकि 2**0.5पूर्व -calculated है, CPython में:

import dis 

def f(): 
    return 2**0.5 

print dis.dis(f) 

प्रिंट

2   0 LOAD_CONST    3 (1.4142135623730951) 
      3 RETURN_VALUE   

जहां लगातार नाव sqrt (2) = 1.414 देखें ...

यदि आप संख्याओं के सरणी में हेरफेर करते हैं, तो न्यूमपी sqrt एक अन्य उत्तर में उल्लिखित तरीका है।

6

मुझे लगता है कि गणित पुस्तकालय जितना तेज़ होगा उतना तेज़ होगा जितना आप स्वयं लिख सकते हैं। लेकिन अगर आप अपना खुद लिखना चाहते हैं, तो यहां एक एल्गोरिदम है। मुझे पायथन नहीं पता, इसलिए मैं बस कुछ छद्म कोड लिखूंगा।

function sqrt(x) 
    lastGuess=x/2 
    loop 
    guess=(lastGuess+x/lastGuess)/2 
    if abs(guess-lastGuess)<.000001 // or whatever threshold you want 
     exit loop 
    lastGuess=guess 
    return guess 

और स्यूडोकोड अजगर का अनुवाद:

def sqrt(x): 
    last_guess= x/2.0 
    while True: 
     guess= (last_guess + x/last_guess)/2 
     if abs(guess - last_guess) < .000001: # example threshold 
      return guess 
     last_guess= guess 
+0

+1 :) –

5

कुछ विशेष मामलों आप तूफानी गति के लिए कार्यक्रम आकार व्यापार सकते हैं। एक बड़ी सरणी बनाएं और प्रत्येक वर्ग रूट ऑपरेशन के लिए प्री-गणना परिणाम (इंडेक्स के रूप में इनपुट मान का उपयोग करके) स्टोर करें। यह बहुत सीमित है लेकिन आपको कुछ भी तेज नहीं मिलेगा।

वर्ग की गणना के लिए

+0

यदि मान सभी छोटे पूर्णांक हैं, तो यह काम कर सकता है। यदि मूल्य मनमानी वास्तविक संख्या हैं, तो यह काम नहीं करेगा। साथ ही, यह केवल तभी काम करता है जब आप एक ही संख्या को कई बार दिखाने की उम्मीद करते हैं। यहां तक ​​कि उस पर, हजारों संख्याओं की वर्ग जड़ों की गणना करने के बजाय जो इनपुट में कभी दिखाई नहीं दे सकते हैं, मैं एक कैश बनाना चाहता हूं और पहली बार इसकी आवश्यकता होने पर वर्ग रूट की गणना करता हूं, उसके बाद कैश से मूल्य का उपयोग करता है। – Jay

0

अजगर कोड का टुकड़ा (कि कैसे भूकंप यह किया है)। यह पहला प्रारंभिक अनुमान बनाता है, और यदि अनुमान पर्याप्त नहीं है तब तक यह अनुमान लगाया जाता है कि हमारे पास

def gen_square_root_v1(number, epsilon): 

    #boundary condition check 

    if number == '1': 
     return 1 

    elif number <= 0: 
     print('this computes square root for positive numbers only') 

    else: 
     pass 


    prev_estimate = number/2 

    while True: 

     #each itearation, calculate a new estimate 
     new_estimate = (prev_estimate + number/prev_estimate)/2 

     #Alternatively can use if abs(new_estimate - prev_estimate) < epsilon: 

     #check the difference between square of new_estimate and number 
     if abs(new_estimate * new_estimate - number) < epsilon: 
     return prev_estimate 

    #if guess is not good enough, use it to make the next guess   
    prev_estimate = new_estimate 


#call the function  
print(gen_square_root_v1(16,1e-5)) 
संबंधित मुद्दे