2014-10-27 11 views
7

मैं बिटवाई ऑपरेटरों में एक विशेषज्ञ नहीं हूं, लेकिन मैं प्रायः एक पैटर्न देखता हूं जिसका प्रयोग प्रतियोगिताओं में 256k डेमो के प्रोग्रामर द्वारा किया जाता है। Math.floor() फ़ंक्शन का उपयोग करने के बजाय, डबल bitwise नहीं ऑपरेटर ~~ (शायद तेज़?) का उपयोग किया जाता है।क्यों: Math.floor (2e + 21)! = ~~ (2e + 21)

इस तरह:

Math.floor(2.1); // 2 
~~2.1 // 2 

खोजें से पता चला अधिक पैटर्न है कि एक ही तरह से इस्तेमाल किया देखते हैं कि:

2.1 | 0 // 2 
2.1 >> 0 // 2 

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

Math.floor(2e+21); // 2e+21 
~~2e+21; // -1119879168 
2e+21 | 0; // -1119879168 

हुड के नीचे क्या हो रहा है?

+8

[बिटवाई ऑपरेटर मूल्यों को 32 बिट पूर्णांक के रूप में मानते हैं] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators): * "सभी bitwise ऑपरेटरों के संचालन दो के पूरक प्रारूप में हस्ताक्षरित 32-बिट पूर्णांक में परिवर्तित हो जाते हैं। "* हुड के तहत: http://www.ecma-international.org/ecma-262/5.1/#sec-11.4.8 –

+1

एक नोट के रूप में, [प्रोग्रामिंग पहेलियाँ और कोड गोल्फ एसई] (http://codegolf.stackexchange.com/help/on-topic) आपके लिए यह पता लगाने के लिए एक उपयुक्त स्थान होगा कि '~~' क्यों उपयोग किया जाता है। 'Math~floor (n) 'के विपरीत' ~~ 'का उपयोग करने का एक बड़ा लाभ यह है कि यह 11 अक्षरों को बचाता है, जो कार्य को कम से कम एक प्रोग्राम के रूप में लिखने के लिए सहेजे जाने वाले बाइट्स की एक बड़ी मात्रा है। – Compass

+0

संभावित डुप्लिकेट [जावास्क्रिप्ट में ~~ ("डबल टिल्डे") क्या करता है?] (Http://stackoverflow.com/questions/4055633/what-does-double-tilde-do-in-javascript) –

उत्तर

4

फ़ेलिक्स किंग ने बताया कि संख्या 32 बिट हस्ताक्षरित पूर्णांक में परिवर्तित हो रही है। 2e9 एक हस्ताक्षरित पूर्णांक की अधिकतम सकारात्मक मूल्य से कम है, इसलिए इस काम करता है:

~~(2e9) //2000000000 

लेकिन जब आप 2e10 के लिए जाना, यह सब बिट का उपयोग नहीं कर सकते हैं तो यह सिर्फ न्यूनतम 32 बिट और रूपांतरित होता लेता है किसी पूर्णांक पर कि:

~~(2e10) //-1474836480 

आप किसी अन्य बिटवाइज़ ऑपरेटर का उपयोग और इस बात की पुष्टि है कि यह सबसे कम 32 बिट हथियाने है इसकी पुष्टि कर सकते हैं:

2e10 & 0xFFFFFFFF // also -1474836480 
~~(2e10 & 0xFFFFFFFF) // also -1474836480 

Math.floor बड़ी संख्या के लिए खाते में करने के लिए बनाया गया है, इसलिए अगर एक बड़ी श्रृंखला पर सटीकता महत्वपूर्ण है तो आपको इसका उपयोग करना चाहिए।

यह भी ध्यान दें: ~~ छंटनी कर रहा है, जो केवल सकारात्मक संख्याओं के लिए फर्श के समान है। यह नकारात्मक के लिए काम नहीं करेगा:

Math.floor(-2.1) // -3 
~~(-2.1) // -2 
2

रूप MDN Docs में कहा गया है, और यहाँ मैं बोली,

सभी बिटवाइज़ ऑपरेटर्स की ऑपरेंड दो के पूरक प्रारूप में हस्ताक्षर किए गए 32-बिट पूर्णांक में बदल रही हैं ।

यह था मतलब है जब आप उदाहरण ~ के लिए एक बिटवाइज़ ऑपरेटर लागू होते हैं,, 2.1 लिए यह पहली बार एक पूर्णांक में बदल जाती है, और उसके बाद ही ऑपरेटर लागू किया है। यह सकारात्मक संख्याओं के लिए प्रभावशाली ढंग से गोल (मंजिल) प्रभावी ढंग से प्राप्त करता है।

इन ऑपरेटरों का उपयोग क्यों किया जाता है, Math.floor को समझने के लिए बहुत अच्छे के बजाय, दो मुख्य कारण हैं। एक के लिए, एक ही परिणाम प्राप्त करने के लिए ये ऑपरेटर considerably faster हो सकते हैं। प्रदर्शन के अलावा, कुछ लोग बस सबसे छोटा कोड संभव चाहते हैं। आपके द्वारा वर्णित सभी तीन ऑपरेटर एक ही प्रभाव प्राप्त करते हैं, लेकिन ~~ बस सबसे छोटा होता है, और तर्कसंगत रूप से याद रखने में सबसे आसान होता है।

यह देखते हुए कि बिटर ऑपरेटरों को लागू करने से पहले पूर्णांक रूपांतरण की फ्लोट होती है, देखते हैं कि ~~ के साथ क्या होता है। मैं शॉर्टनेस के लिए 32 की बजाय 8 बिट्स का उपयोग करके हमारे लक्ष्य संख्या (2, 2.1 से कनवर्ट करने के बाद) का प्रतिनिधित्व करूंगा।

2: 0000 0010 
~2: 1111 1101 (-3) 
~~2: 0000 0010 

तो, जैसा कि आप देख, हम केवल पूर्णांक भाग पुनः प्राप्त करने के एक ऑपरेटर लागू होते हैं, लेकिन हम केवल एक बिटवाइज़ नहीं लागू नहीं कर सकते, क्योंकि यह गंदगी परिणाम होगा। हम इसे दूसरे ऑपरेटर को लागू वांछित मूल्य पर वापस ले जाते हैं।


अपने अंतिम उदाहरण के संबंध में, ध्यान दें कि जिस नंबर पर आप परीक्षण कर रहे हैं, 2e + 21, अपेक्षाकृत बड़ी संख्या है। यह एक 2 है जिसके बाद बीस एक शून्य है। यह बस 32-बिट पूर्णांक के रूप में फिट नहीं होता है (डेटा-प्रकार जिसे इसे परिवर्तित किया जा रहा है, जब आप बिटवाई ऑपरेटरों को लागू करते हैं)। बस अपनी संख्या के बीच का अंतर देखें और 32-बिट हस्ताक्षरित पूर्णांक क्या प्रतिनिधित्व कर सकता है।

Max. Integer:    2147483647 
     2e+21: 2000000000000000000000 

बाइनरी के बारे में कैसे?

Max. Integer:          01111111111111111111111111111111 
     2e+21: 11011000110101110010011010110111000101110111101010000000000000000000000 

काफी बड़ा, हुह?

हुड के नीचे वास्तव में क्या होता है यह है कि जावास्क्रिप्ट को आपकी बड़ी संख्या 32 बिट्स में प्रस्तुत करने के लिए छंटनी कर रहा है।

110110001101011100100110101101110001011 10111101010000000000000000000000 
^----   Junk    ----^ 

जब हम अपने छंटनी संख्या को दशमलव में परिवर्तित करते हैं, तो हम जो भी देख रहे हैं उसे वापस लेते हैं।

Bin: 10111101010000000000000000000000 
Dec: -1119879168 

इसके विपरीत, बड़ी संख्या के लिए Math.floor खातों और, उन्हें छोटा टाल हालांकि सटीक जो यह धीमी होने के लिए संभावित कारणों में से एक है।

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