2009-07-07 8 views
26

अजीब और यहां तक ​​कि पूर्णांक की जांच करने के लिए, सबसे कम बिट मॉड्यूल का उपयोग करने से अधिक कुशल जांच रहा है?अजीब संख्याओं की जांच करते समय% से तेज़ और तेज है?

>>> def isodd(num): 
     return num & 1 and True or False 

>>> isodd(10) 
False 
>>> isodd(9) 
True 
+1

"और सही या गलत" के साथ क्या है? – FogleBird

+14

यदि आप एक बूलियन परिणाम प्राप्त करने का प्रयास कर रहे हैं, तो बस बूल (num और 1) – FogleBird

+0

करें मैं पाइथन 3.1 – riza

उत्तर

57

हाँ। मानक पुस्तकालय में timeit मॉड्यूल यह है कि आप उन चीजों पर कैसे जांच करते हैं। उदा:

AmAir:stko aleax$ python -mtimeit -s'def isodd(x): x & 1' 'isodd(9)' 
1000000 loops, best of 3: 0.446 usec per loop 
AmAir:stko aleax$ python -mtimeit -s'def isodd(x): x & 1' 'isodd(10)' 
1000000 loops, best of 3: 0.443 usec per loop 
AmAir:stko aleax$ python -mtimeit -s'def isodd(x): x % 2' 'isodd(10)' 
1000000 loops, best of 3: 0.453 usec per loop 
AmAir:stko aleax$ python -mtimeit -s'def isodd(x): x % 2' 'isodd(9)' 
1000000 loops, best of 3: 0.461 usec per loop 

जैसा कि आप देख, मेरे (प्रथम दिन पर == वर्ष == धीमी ;-) मैकबुक एयर, & समाधान 7 और 18 के बीच repeatably नैनोसेकंड % समाधान की तुलना में तेजी है।

timeit न केवल आपको बताता है कि क्या तेजी से है, लेकिन द्वारा कितना, जो आमतौर पर पता चलता है कि यह कैसे परम महत्वहीन है (बस परीक्षण कई बार चलाने) (आप वास्तव में देखभाल के बारे में 10 नैनोसेकंड 'अंतर करते हैं, जब भूमि के ऊपर फ़ंक्शन को कॉल करने के बारे में 400 है?! -) ...

समझदार प्रोग्रामर जो सूक्ष्म अनुकूलन अनिवार्य रूप से अप्रासंगिक हैं, एक असंभव कार्य साबित हुआ है - भले ही यह 35 वर्ष हो (जिस पर कंप्यूटर के आदेश प्राप्त हुए हैं तीव्रता तेजी से!) चूंकि Knuth wrote

हमें क्षमता के बारे में भूल जाना चाहिए, समय के 97% के बारे में बताएं: समयपूर्व अनुकूलन सभी बुराइयों की जड़ है।

जो उन्होंने समझाया है, होरेस से भी पुराने कथन से उद्धरण है। मुझे लगता है कि हर कोई पूरी तरह से आश्वस्त है कि उनका मामला शेष 3% में आता है!

बजाय बेहद दोहरा "यह कोई बात नहीं" का, हम मानक अजगर पुस्तकालय मॉड्यूल timeit में डाल (विशेष रूप से टिम पीटर्स वहाँ सम्मान के हकदार), बनाता है कि यह trivially आसान ऐसे सूक्ष्म मानक को मापने और इस तरह के की सुविधा देता है, कम से कम कुछ प्रोग्रामर खुद को समझाने कि, हममम, इस मामले में 97% समूह में गिरावट है -!)

+0

कंपाइलर उन निर्देशों को अनुकूलित करने के लिए नहीं जा रहा है? अगर यह दिखाता है तो मेरी पाइथन-अज्ञानता क्षमा करें। – GManNickG

+2

नहीं, पाइथन कंपाइलर को स्वयं को सरल, भरोसेमंद और तेज़ होने के लिए अनुकूलित किया गया है - यह ऑप्टिमाइज़ेशन नहीं करता है जैसे ऑपरेशन को उपयोग में बदलना (जिसके लिए यह अनुमान लगाया जाना चाहिए कि 'x' हमेशा पूर्णांक है, के लिए उदाहरण)। यदि आपको इस तरह के निम्न-स्तरीय अनुकूलन की आवश्यकता है (यानी यदि हर नैनोसेकंद मायने रखता है) तो साइको का प्रयास करें। –

+1

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

23

पूरी तरह से ईमानदारी से कहूं तो मैं यह मायने रखता है नहीं लगता।

पहला मुद्दा पठनीयता है। अन्य डेवलपर्स के लिए और अधिक समझ क्या है? मैं, व्यक्तिगत रूप से, किसी संख्या की समानता/विषमता की जांच करते समय एक मॉड्यूल की अपेक्षा करता हूं। मैं उम्मीद करता हूं कि अधिकांश अन्य डेवलपर्स एक ही चीज़ की अपेक्षा करेंगे। एक अलग, और अप्रत्याशित, विधि शुरू करके, आप कोड पढ़ सकते हैं, और इसलिए रखरखाव, और अधिक कठिन।

दूसरा यह तथ्य है कि ऑपरेशन करते समय शायद आपके पास कभी भी बाधा नहीं होगी। मैं अनुकूलन के लिए हूं, लेकिन शुरुआती अनुकूलन किसी भी भाषा या पर्यावरण में सबसे बुरी चीज है। यदि, किसी कारण से, यह निर्धारित करना कि कोई संख्या एक बाधा है या बाधा है, तो समस्या को हल करने का सबसे तेज़ तरीका ढूंढें। हालांकि, यह मुझे अपने पहले बिंदु पर वापस लाता है - पहली बार जब आप नियमित रूप से लिखते हैं, तो इसे संभवतः सबसे अधिक पढ़ने योग्य तरीके से लिखा जाना चाहिए।

+0

मुझे इस पर कम वोट देने की उम्मीद है, लेकिन मुझे लगता है कि यह किसी भी व्यक्ति के लिए एक महत्वपूर्ण बिंदु है (या कोई भी समान) सवाल है, इसलिए यह रहने जा रहा है। –

+0

एक डाउन वोट पर्स नहीं है ... लेकिन, यह "स्पष्ट" विकल्पों को प्रोफाइल करने और सबसे तेज़ पसंद करने के लिए इस तरह के मामलों में पाइथोनिक समाधान रहा है। –

+2

semiuseless: मैं अभी भी पायथन सीख रहा हूं, लेकिन मुझे व्यक्तिगत रूप से लगता है कि मॉड्यूल ऑपरेटर अधिक पाइथोनिक होगा क्योंकि आप उम्मीद कर रहे हैं। यह मेरे लिए कम से कम, अधिक स्पष्ट और स्पष्ट है। –

4

"वापसी संख्या & 1 और सही या गलत"? वाह! यदि आप गति-पागल हैं (1) "वापसी संख्या & 1" (2) इनलाइन करें: if somenumber % 2 == 1 सुगम है और isodd(somenumber) धड़कता है क्योंकि यह पायथन फ़ंक्शन कॉल से बचाता है।

+2

हाँ, फ़ंक्शन कॉल से परहेज करना एक बड़ी जीत है (हालांकि == 1 वास्तव में अनावश्यक है) - 450 से 300 नैनोसेकंड के कॉल कटौती से बचने के लिए या तो मैंने अपने जवाब में मापा। –

4

जॉन एक अच्छा मुद्दा लाता है।असली ओवरहेड फ़ंक्शन कॉल में है:

[email protected] ~> python -mtimeit -s'9 % 2' 
10000000 loops, best of 3: 0.0271 usec per loop 
[email protected] ~> python -mtimeit -s'10 % 2' 
10000000 loops, best of 3: 0.0271 usec per loop 

[email protected] ~> python -mtimeit -s'9 & 1' 
10000000 loops, best of 3: 0.0271 usec per loop 
[email protected] ~> python -mtimeit -s'9 & 1' 
10000000 loops, best of 3: 0.0271 usec per loop 

[email protected] ~> python -mtimeit -s'def isodd(x): x % 2' 'isodd(10)' 
1000000 loops, best of 3: 0.334 usec per loop 
[email protected] ~> python -mtimeit -s'def isodd(x): x % 2' 'isodd(9)' 
1000000 loops, best of 3: 0.358 usec per loop 

[email protected] ~> python -mtimeit -s'def isodd(x): x & 1' 'isodd(10)' 
1000000 loops, best of 3: 0.317 usec per loop 
[email protected] ~> python -mtimeit -s'def isodd(x): x & 1' 'isodd(9)' 
1000000 loops, best of 3: 0.319 usec per loop 

दिलचस्प बात यह है कि दोनों विधियां फ़ंक्शन कॉल के बिना एक ही समय में पुनर्स्थापित होती हैं।

+0

यदि मैं फ़ंक्शन को प्रतिस्थापित करने के लिए लैम्ब्डा का उपयोग करता हूं तो क्या होगा? isodd = lambda num: num और 1 और सही या गलत – riza

10

आपके द्वारा प्राप्त सर्वोत्तम अनुकूलन पर एक फ़ंक्शन में डाल दिया गया है। 'number % 2' और 'संख्या & 1' विषम/समानता की जांच करने के बहुत ही सामान्य तरीके हैं, अनुभवी प्रोग्रामर तुरंत पैटर्न को पहचानेंगे, और आप हमेशा एक टिप्पणी में फेंक सकते हैं जैसे कि # # यदि संख्या अजीब है, तो ब्ला ब्ला ब्लाह ' आपको वास्तव में स्पष्ट होने की आवश्यकता है।

# state whether number is odd or even 
if number & 1: 
    print "Your number is odd" 
else: 
    print "Your number is even" 
+0

क्या आप कृपया बता सकते हैं कि '%' और 'और' पायथन में क्या करते हैं? – LWZ

+1

यह संख्या और 1 कैसे अजीब संख्या देता है? – sam

1

अलावा बुराई अनुकूलन से, इसे दूर बहुत मुहावरेदार "var% 2 == 0" है कि हर सांकेतिक शब्दों में बदलनेवाला दो बार देख बिना समझता है लेता है। तो यह बहुत कम लाभ के लिए पाइथन जेन का भी उल्लंघन करता है।

इसके अलावा a = b और सही है या गलत यह सच है, तो संख्या से

वापसी बेहतर पठनीयता के लिए ले लिया है & 1 और झूठी

0

था ऊपर जवाब में से वाकई हैरान कोई भी दोनों चर सेटअप किया था (शाब्दिक समय अलग कहानी है) और कोई फ़ंक्शन आमंत्रण नहीं है (जो स्पष्ट रूप से "निचली शर्तों" को छुपाता है)। Ipython के समय से उस समय पर अटक गया, जहां मुझे स्पष्ट विजेता x & 1 मिला - python2.6 (~ python3.1 का उपयोग कर ~ 12%) का उपयोग कर ~ 18% के लिए बेहतर।

मेरी बहुत पुरानी मशीन पर:

$ python -mtimeit -s 'x = 777' 'x&1' 
10000000 loops, best of 3: 0.18 usec per loop 
$ python -mtimeit -s 'x = 777' 'x%2' 
1000000 loops, best of 3: 0.219 usec per loop 

$ python3 -mtimeit -s 'x = 777' 'x&1' 
1000000 loops, best of 3: 0.282 usec per loop 
$ python3 -mtimeit -s 'x = 777' 'x%2' 
1000000 loops, best of 3: 0.323 usec per loop 
0

अजगर 3.6 उत्तर का उपयोग करना कोई है। 2017 एमबीपी पर दिए गए कोड का उपयोग करने से पता चलता है कि मॉड्यूलो का उपयोग करना तेज है। , समारोह एक बड़े भूमि के ऊपर है कहता है, फिर भी, जैसा कि अन्य उत्तर में सुझाव दिया

$ python3 -m odd 
is_even_modulo: 0:00:14.347631 
is_even_and: 0:00:17.476522 
$ python3 --version 
Python 3.6.1 

को दूर करने में यह पता चलता है कि सापेक्ष बिटवाइज़ से और अजगर 3.6.1 में अब भी तेजी से होता है:

# odd.py 
from datetime import datetime 

iterations = 100_000_000 


def is_even_modulo(n): 
    return not n % 2 


def is_even_and(n): 
    return not n & 1 


def time(fn): 
    start = datetime.now() 
    for i in range(iterations, iterations * 2): 
     fn(i) 
    print(f'{fn.__name__}:', datetime.now() - start) 


time(is_even_modulo) 
time(is_even_and) 

इस परिणाम देता है :

# odd.py 
from datetime import datetime 

iterations = 100_000_000 


def time_and(): 
    start = datetime.now() 
    for i in range(iterations): 
     i & 1 
    print('&:', datetime.now() - start) 


def time_modulo(): 
    start = datetime.now() 
    for i in range(iterations): 
     i % 2 
    print('%:', datetime.now() - start) 


time_modulo() 
time_and() 

परिणाम:

$ python3 -m odd 
%: 0:00:05.134051 
&: 0:00:07.250571 

बोनस: यह पता चला है कि इसमें पाइथन 2.7 में चलाने के लिए लगभग दोगुना समय लगता है।

$ time python2 -m odd 
('&:', '0:00:20.169402') 
('%:', '0:00:19.837755') 

real 0m41.198s 
user 0m39.091s 
sys 0m1.899s 
$ time python3 -m odd 
&: 0:00:11.375059 
%: 0:00:08.010738 

real 0m19.452s 
user 0m19.354s 
sys 0m0.042s