सशर्त अभिव्यक्ति में बिटवाइज़ ऑपरेटर का उपयोग करना कब उचित है?


15

सबसे पहले, कुछ पृष्ठभूमि: मैं एक आईटी शिक्षक-इन-ट्रेनिंग हूं और मैं जावा के बुलियन ऑपरेटरों को अपनी 10 वीं कक्षा की कक्षा में लाने की कोशिश कर रहा हूं। मेरे शिक्षक-संरक्षक ने मेरे द्वारा तैयार की गई एक वर्कशीट को देखा और टिप्पणी की कि मैं उन्हें केवल एक & या का उपयोग करने दे सकता हूं संचालकों को निरूपित करना, क्योंकि वे "ऐसा ही करते हैं"।

मुझे & && के बीच अंतर के बारे में पता है।
& "बिट-ट्विडलिंग" करने के लिए पूर्णांक के बीच उपयोग के लिए एक बिटवाइज़र ऑपरेटर है।
&& एक सशर्त ऑपरेटर है जो बूलियन मूल्यों के बीच उपयोग के लिए है।

इस बात को साबित करने के लिए कि ये ऑपरेटर हमेशा "एक ही काम नहीं करते हैं" मैं एक उदाहरण खोजने के लिए निकलता हूं जहां बूलियन मूल्यों के बीच बिटवाइज़ का उपयोग करने से त्रुटि पैदा होगी। मुझे यह उदाहरण मिला

boolean bitwise;
boolean conditional;
int i=10, j=12;
bitwise = (i<j) | ((i=3) > 5); // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10; 
conditional = (i<j) || (i=3) > 5 ;  // value of i after oper: 10
System.out.println(conditional+ " "+ i);
i=10; 
bitwise = (i>j) & (i=3) > 5;   // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10; 
conditional = (i>j) && (i=3) > 5;  // value of i after oper: 10
System.out.println(conditional+ " "+ i);

इस उदाहरण से पता चलता है कि यदि अभिव्यक्ति के दूसरे छमाही तक किसी मूल्य को बदलना है, तो इससे परिणामों के बीच अंतर होगा, क्योंकि बिटवाइज़ एक उत्सुक ऑपरेटर है, जबकि सशर्त एक शॉर्ट सर्किट के रूप में व्यवहार करता है (दूसरे का मूल्यांकन नहीं करता है आधा, अगर पहली छमाही && के मामले में झूठी है और ||

मेरे पास इस उदाहरण के साथ एक मुद्दा है। जब आप इस पर एक तुलना करेंगे, तो आप उसी समय एक मूल्य क्यों बदलना चाहेंगे? यह कोड करने के लिए एक मजबूत तरीका नहीं लगता है। मैं हमेशा अपने उत्पादन कोड में एक ही लाइन में कई ऑपरेशन करने का विरोध करता रहा हूं। ऐसा लगता है कि कोई "कोडिंग काउबॉय" है, जिसमें कोई विवेक नहीं है क्योंकि उसके कोड की स्थिरता क्या होगी। मुझे पता है कि कुछ डोमेन में कोड को यथासंभव कॉम्पैक्ट होना चाहिए, लेकिन निश्चित रूप से यह सामान्य रूप से खराब अभ्यास है?

मैं && और || ओवर एंड | क्योंकि यह सॉफ्टवेयर इंजीनियरिंग में एक स्वीकृत कोडिंग कन्वेंशन है

लेकिन क्या कोई मुझे एक बेहतर, यहां तक ​​कि वास्तविक दुनिया दे सकता है, उदाहरण के लिए एक सशर्त अभिव्यक्ति में बिटवाइज़ ऑपरेटर का उपयोग करना?

जवाबों:


16

यह उचित है जब आप मास्किंग ऑपरेशन कर रहे हों

अगर ((a & b)> 0) {...}

जहां और बी पूर्णांक हैं

|| और | और && और & विनिमेय नहीं हैं

| और & amost कभी भी अपने आप से सशर्त अभिव्यक्ति में दिखाई नहीं देगा (आपके द्वारा शामिल लिंक का बिंदु यह है कि ऐसी चीजें अक्सर त्रुटियां होती हैं)

संपादित करें: अपने संरक्षक के साथ बहस न करें; यदि आप जीतते हैं, तो भी आप हार जाते हैं। इसके बजाय, समझाएं कि आप तार्किक ऑपरेटरों और बिटवाइज़ ऑपरेटरों को एक ही पाठ में मिलाकर छात्रों को भ्रमित नहीं करना चाहते हैं। आप यह समझा सकते हैं कि यदि i = 3 और j = 2 है तो i & j = 2, जबकि i && j एक त्रुटि है। हालांकि, सरल व्याख्या यह है कि आप बूलियन (तार्किक) संचालकों को पढ़ा रहे हैं, इसलिए विशेष-केस बिटवाइज समकक्षों में फेंकना पाठ के मुख्य बिंदु से एक व्याकुलता है। संरक्षक को "गलत" बनाने की आवश्यकता नहीं है, और काउंटर-उदाहरणों का उत्पादन करने की आवश्यकता नहीं है। पाठ का ध्यान बूलियन ऑपरेटरों पर है, न कि बिटवाइज़ ऑपरेटरों पर।

एक कोरोलरी के रूप में, जब आप बिटवाइज़ ऑपरेटरों को पढ़ाना शुरू करते हैं, तो विशेष मामलों को दिखाने की कोई आवश्यकता नहीं होती है जहाँ + और - के समान परिणाम उत्पन्न होते हैं और |


उपरोक्त कोड गलत नहीं है, हालांकि यह भ्रामक हो सकता है लेकिन जैसा कि यह खड़ा है कि कोड में त्रुटि नहीं है? मैं सहमत हूं कि इस तरह से बिटवाइज़ ऑपरेटरों का उपयोग करना बहुत ही पठनीय नहीं है, अगर मैं इसे कोड समीक्षा में देखता हूं, तो मुझे यह पसंद नहीं आएगा, लेकिन यह कानूनी जावा (और सी # भी है, जो System.out.println की अनदेखी करता है)।
स्टीव

@Steven A. Lowe को जवाब देने के लिए धन्यवाद। आपने कहा "|| | | और && और &" विनिमेय नहीं हैं "लेकिन bitwise = !(true & true == false);और condition = !(true && true == false);क्या दोनों सत्य का मूल्यांकन करेंगे, इसलिए इस मामले में वे विनिमेय हैं? Syntactically शायद, क्योंकि कोड अभी भी संकलित है। मैं इस बात से सहमत हूँ कि इनका उपयोग अलग-अलग चीज़ों के लिए शब्दार्थ रूप से किया जाता है, जैसा कि मैंने पैराग्राफ 2 में उल्लेख किया है। आप कहते हैं कि! और "लगभग कभी भी खुद से सशर्त दिखाई नहीं देता"। मैं इन "लगभग कभी नहीं" मामलों की तलाश कर रहा हूं, और सोच रहा हूं कि क्या वे वैध रूप से मौजूद हैं।
देवरशा १४'११ को

@Deerasha: || और && केवल बूलियन पर कार्य करते हैं । और | पूर्णांक और बूलियन्स पर काम करते हैं - बूलियन्स में हेरफेर करने के लिए बिटवाइज ऑपरेटरों ( कई बिट्स पर काम करने का इरादा ) का उपयोग करने में बहुत कम बिंदु है , और परित्याग के साथ ऐसा करने से भ्रामक कोड और अप्रत्याशित व्यवहार हो सकते हैं (अर्थात यदि आप गलती से एक पूर्णांक के बजाय एक पूर्णांक का उपयोग करते हैं। बूलियन, बिटवाइज ऑपरेटर शिकायत नहीं करेंगे)
स्टीवन ए। लोव

हां @ हाईवे, संकलक इसे अस्वीकार नहीं करता है, लेकिन यह उनका उपयोग करने का सही तरीका नहीं है, मैं प्रकाशित कोडिंग मानक से जुड़ा हुआ हूं। क्या मैं आराम से इसे खारिज करने पर आराम कर सकता हूं क्योंकि यह एक कोडिंग मानक का पालन नहीं करता है, या जावा को शायद यह संकेत देना चाहिए कि यह एक अनुचित उपयोग है?
देवरशा

2
@Steven A. Lowe: अगर i = 3 और j = 2 है तो i & j = 2 है, जबकि i && j त्रुटि है। यह शानदार है! यह सरल है और यह बात बनाता है। 10 वीं कक्षा के स्तर पर यह भी एक गलत गलती है, क्योंकि वे अभी भी बूलियन प्रकार के लिए उपयोग किए जा रहे हैं और ऑपरेटर क्या लागू करेंगे। आपको बहुत - बहुत धन्यवाद! मेरे गुरु के साथ बहस न करने की बड़ी सलाह।
देवरशा

12

गैर-बिटवाइज़ ऑपरेटर &&और ||शॉर्ट-सर्किट ऑपरेटर हैं। दूसरे शब्दों में &&, यदि LHS गलत है, तो RHS का मूल्यांकन कभी नहीं किया जाएगा; साथ ||अगर एलएचएस सत्य है, तभी आरएचएस मूल्यांकन किया जाना कभी नहीं होगा। दूसरी ओर, बिटवाइज़ ऑपरेटर &और |गैर-शॉर्ट-सर्किट हैं, और हमेशा एलएचएस और आरएचएस दोनों का मूल्यांकन करेंगे। अन्यथा, वे एक ifबयान में बराबर हैं ।

केवल समय जब मैं गैर-शॉर्ट-सर्किट ऑपरेटरों का उपयोग करने में मूल्य देख सकता हूं, अगर आरएचएस में कुछ प्रकार के वांछनीय दुष्प्रभाव हैं जो आप सभी मामलों में होना चाहते हैं। मैं एक विशिष्ट उदाहरण के बारे में नहीं सोच सकता जहाँ आप यह चाहते हैं, और मुझे विश्वास नहीं है कि यह अच्छा अभ्यास है, लेकिन यही अंतर है।


1
+1। बिल्कुल सही, जब बूलियंस बिटवाइज़ और लॉजिकल ऑपरेटर्स की तुलना करना हमेशा एक ही परिणाम देता है, लेकिन (जावा और C # में कम से कम) केवल लॉजिकल ऑपरेटर्स शॉर्ट सर्किट।
स्टीव

जवाब देने के लिए शुक्रिया। आपका पैराग्राफ 1 वही था जो मैं अपने पैराग्राफ 4 में प्राप्त करने की कोशिश कर रहा था, यह कहते हुए कि बिटवाइज़ एक उत्सुक ऑपरेटर है जबकि सशर्त एक शॉर्ट सर्किट के रूप में व्यवहार करता है । आपका पैरा 2 वह चिंता है जो मैंने अपने पैरा 5 में वर्णित की है। इसलिए मैं अंतर से अवगत हूं लेकिन मैं उस विशिष्ट उदाहरण की तलाश कर रहा हूं जो न तो आप और न ही मैं सोच सकता हूं।
देवरशा

7

सामान्य दार्शनिक उत्तर यह है कि बूलियन ऑपरेटरों के लिए बिटवाइज़ ऑपरेटरों का उपयोग करना असामान्य है और कोड को पढ़ने के लिए कठिन बना देता है। व्यवहार में (कोड के लिए जो उत्पादन में है), अधिक पठनीय कोड बनाए रखना आसान है और इस प्रकार अधिक वांछनीय है।

शॉर्ट-सर्किट ऑपरेटरों की आवश्यकता के वास्तविक दुनिया में उपयोग के लिए, जैसे मामले देखें:

if (args.length > 0 && args[0] == 'test') ....

if (b != NULL && b.some_function()) ...

if (b == NULL || b.some_function()) ...

इस प्रकार के ऑपरेशन वास्तविक-दुनिया कोड में अक्सर दिखाई देते हैं।


TFA। मैं अपने 15 साल के बच्चों को कैसे समझाऊं कि 1 &2 की तुलना में "पढ़ने में कठिन" है? मेरे पास एक उदाहरण नहीं है जिसमें 2 ऑपरेटर बूलियन ऑपरेंड के लिए उसी तरह से काम नहीं करते हैं। मैं कोड को बनाए रखने के लिए अधिक पठनीय और आसान के बारे में आपकी बात पर सहमत हूं। मैं उन्हें सुंदर कोड लिखने के लिए प्रोत्साहित करना चाहता हूं। लेकिन मेरे बैग के औजारों में कुछ सबूत होने के कारण "मैं ऐसा कह रहा था" की तुलना में अधिक आश्वस्त होगा। मुझे लगता है कि यह उस लिंक पर एक मानक के रूप में कहा गया है, और मुझे उस पर भरोसा करना पड़ सकता है अगर मुझे वह उदाहरण नहीं मिलता है जिसकी मुझे तलाश है। जैसा कि मैंने @Steve Haigh से पूछा: क्या जावा को इसे अनुचित उपयोग के रूप में इंगित करना चाहिए?
देवरशा

@Deerasha मैं आपके संरक्षक के साथ एक तर्क के बारे में अधिक सोच रहा था। वर्ग के लिए भी उन्हें यह बताने की कोशिश न करें कि आप तार्किक स्थितियों के लिए बिटवाइज़ ऑपरेटरों का उपयोग कर सकते हैं।
कैथी वान स्टोन

4

यदि आप Bitmask enumerations की तुलना करते हैं तो आप बिटकॉइन ऑपरेटरों का उपयोग करेंगे। उदाहरण के लिए, आपके पास राज्यों की एक गणना और एक वस्तु है जो उन राज्यों में से एक से अधिक में हो सकती है। इस स्थिति में, आप एक बिटवाइज़ करेंगे या एक से अधिक राज्यों को अपनी वस्तु पर असाइन करेंगे।

उदाहरण के लिए state = CONNECTED | IN_PROGRESSजहां CONNECTED could be 0x00000001औरIN_PROGRESS 0x00000010

अधिक जानकारी के लिए, फ्लैग एनम डॉक्यूमेंटेशन देखें।


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

मुझे नहीं लगता कि जावा में ऐसा हो सकता है जैसा कि मुझे विश्वास है कि कॉलिंग | या उन मानों पर ऑपरेटर जो बिटवाइज़ नहीं हो सकते हैं और वे केवल एक तार्किक प्रदर्शन करेंगे या करेंगे या &। मुझे याद नहीं है अगर यह जावा में मामला है, लेकिन यह सुनिश्चित करें कि यह C # MSDN में है: "बाइनरी | ऑपरेटरों को अभिन्न प्रकार और बूल के लिए पूर्वनिर्धारित किया जाता है। अभिन्न प्रकार के लिए; - बिटवाइस या इसके ऑपरेंड की गणना करता है। बूल
ऑपरेंड्स

कुछ और शोध के बाद, मुझे पता चला कि केवल एक ही अंतर है | और || और जावा में बूलियन ऑपरेंड के लिए और && शॉर्ट सर्किट व्यवहार है, इसलिए आपके द्वारा वर्णित परिदृश्य वास्तव में संभव नहीं है।
pwny

0

गलत का एक सरल उदाहरण:

int condA=1, condB=2;

if (condA!=0 && condB!=0) {
    // correct!
}
if ((condA & condB)!=0) {
    // never executed
}

यहां आपकी दो स्थितियां हैं, दोनों गैर-शून्य हैं; लेकिन बिटवाइज़ का &परिणाम शून्य होता है।


@ जेवियर: जवाब देने के लिए धन्यवाद, लेकिन मैं थोड़ा भ्रमित हूं। मैं जावा में काम कर रहा हूं, और यह कोड संकलित नहीं करता है। (condA && condB)त्रुटियां, क्योंकि && 2 ints के लिए काम नहीं करता है , केवल 2 बूलियन। (condA & condB)सही होने पर, एक int और जावा में मूल्यांकन करता है, if(int)इसलिए हम यह भी नहीं कह सकते कि यह त्रुटियां भी हैं। आप यह समझने के लिए सबसे पहले हैं कि मैं क्या देख रहा हूँ- बिल्कुल गलत उदाहरण
देवरशा

एक लंबे समय में जावा का उपयोग नहीं किया है ... प्रयास करें (Boolean(condA) && Boolean(condB)) (मुझे लगता Boolean(x)है कि trueगैर-शून्य पूर्णांकों के लिए है, ठीक है?)
जेवियर

नहींं @ जेवियर: इंट से बुलियन तक नहीं डाली जा सकती।
देवरशा

किस बारे में ((condA!=0) && (condB!=0))?
जेवियर

@ जेवियर याय यह संकलित करता है, लेकिन "गलतता" अब if (((condA!=0) && (condB!=0))) { System.out.println("correct"); } if (((condA!=0) & (condB!=0))) { System.out.println("never executed?"); }दोनों प्रिंट स्टेटमेंट को सचित्र नहीं करता है।
देवरशा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.