Java.util की रेखा 294. आयामी स्रोत कहते हैं
if ((n & -n) == n) // i.e., n is a power of 2
// rest of the code
ऐसा क्यों है?
Java.util की रेखा 294. आयामी स्रोत कहते हैं
if ((n & -n) == n) // i.e., n is a power of 2
// rest of the code
ऐसा क्यों है?
(n & (n - 1)) == 0
भी काम करता है (यह सबसे कम क्रम बिट को हटाता है, यदि बिट्स नहीं बचे हैं तो पहले स्थान पर अधिकतम 1 बिट सेट था)।
जवाबों:
विवरण पूरी तरह से सटीक नहीं है क्योंकि (0 & -0) == 0
0 दो की शक्ति नहीं है। इसे कहने का एक बेहतर तरीका है
((n & -n) == n)
जब n दो की शक्ति है, या दो की शक्ति का नकारात्मक है, या शून्य है।
यदि n दो की शक्ति है, तो बाइनरी में n एक शून्य है जिसके बाद शून्य है। -दो पूरक में व्युत्क्रम + 1 है, इसलिए बिट्स इस प्रकार ऊपर की ओर जाती हैं
n 0000100...000
-n 1111100...000
n & -n 0000100...000
यह देखने के लिए कि यह काम क्यों है, दो के पूरक को व्युत्क्रम + 1 मानें, -n == ~n + 1
n 0000100...000
inverse n 1111011...111
+ 1
two's comp 1111100...000
चूँकि आप दो के पूरक प्राप्त करने के लिए एक को जोड़ते समय सभी को एक साथ ले जाते हैं।
यदि n दो were की शक्ति के अलावा कुछ भी नहीं थे, तो परिणाम थोड़ा याद आ जाएगा क्योंकि दोनों के पूरक में उस ले जाने के कारण उच्चतम बिट सेट नहीं होगा।
† - या शून्य या दो की शक्ति का ऋणात्मक ... जैसा कि शीर्ष पर समझाया गया है।
(0 & -0) == 0
, तुरंत पूर्व कथन है if (n <= 0) throw ...
। मतलब यह कि परीक्षण के तहत संख्या उस बिंदु पर कभी 0 (या नकारात्मक) नहीं होगी।
Random.java
जिसकी आलोचना मैंने नहीं की है।
n
है; मैंने इस धारणा की जाँच नहीं की है, लेकिन किसी तरह संदेह है कि एक double
ही तरह से व्यवहार करेगा।
n
"जावा" टैग के प्रकार पर बहुत अच्छे सीमा लगा सकते हैं । या जावा में &
परिभाषित नहीं है । यह केवल पूर्णांक प्रकार और बूलियन पर परिभाषित किया गया है। चूंकि बूलियंस के लिए परिभाषित नहीं किया गया है, हम सुरक्षित रूप से अनुमान लगा सकते हैं कि यह अभिन्न है। double
float
-
n
क्योंकि 2 के पूरक में, -n
है~n+1
।
यदि n
2 की शक्ति है, तो इसका केवल एक बिट सेट है। तो ~n
उस एक को छोड़कर सभी बिट्स सेट है। 1 जोड़ें, और आप फिर से विशेष बिट सेट करते हैं, यह सुनिश्चित करता n & (that thing)
है कि इसके बराबर हैn
।
अनुलग्नक भी सत्य है क्योंकि उस जावा स्रोत में 0 और ऋणात्मक संख्याओं को पिछली पंक्ति द्वारा खारिज किया गया था। यदि n
एक से अधिक बिट सेट हैं, तो उनमें से एक बिट सबसे अधिक है। यह बिट सेट नहीं किया जाएगा +1
क्योंकि इसे "अवशोषित" करने के लिए कम स्पष्ट बिट है:
n: 00001001000
~n: 11110110111
-n: 11110111000 // the first 0 bit "absorbed" the +1
^
|
(n & -n) fails to equal n at this bit.
आपको बिटमैप के रूप में मान देखने की आवश्यकता है कि यह क्यों सच है:
1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
तो अगर दोनों फ़ील्ड 1 हैं तो केवल 1 ही बाहर आएगा।
अब -n एक 2 का पूरक है। यह सभी को बदलता 0
है 1
और यह 1 जोड़ता है।
7 = 00000111
-1 = NEG(7) + 1 = 11111000 + 1 = 11111001
तथापि
8 = 00001000
-8 = 11110111 + 1 = 11111000
00001000 (8)
11111000 (-8)
--------- &
00001000 = 8.
केवल 2 की शक्तियों के (n & -n)
लिए n होगा ।
ऐसा इसलिए है क्योंकि 2 की शक्ति को शून्य के लंबे समुद्र में एकल सेट बिट के रूप में दर्शाया गया है। नकार 1 के समुद्र में सटीक विपरीत, एक एकल शून्य (उस स्थान पर जहां 1 का उपयोग किया जाता है) का उत्पादन करेगा। 1 जोड़ने से निचले वाले को उस स्थान पर स्थानांतरित कर दिया जाएगा जहां शून्य है।
और बिटवाइज़ और (() फिर से 1 को फ़िल्टर करेगा।
दो के पूरक प्रतिनिधित्व में, दो की शक्तियों के बारे में अनोखी बात यह है कि वे सभी 0 बिट्स से मिलकर बने हैं, केवल kth बिट को छोड़कर, जहां n = 2 ^ k:
base 2 base 10
000001 = 1
000010 = 2
000100 = 4
...
दो के पूरक में एक नकारात्मक मूल्य प्राप्त करने के लिए, आप सभी बिट्स को फ्लिप करते हैं और एक को जोड़ते हैं। दो की शक्तियों के लिए, इसका मतलब है कि आपको बाईं ओर 1 एस का एक गुच्छा मिलता है और सकारात्मक मूल्य में 1 बिट शामिल है, और फिर दाईं ओर 0s का एक गुच्छा है:
n base 2 ~n ~n+1 (-n) n&-n
1 000001 111110 111111 000001
2 000010 111101 111110 000010
4 000100 111011 111100 000100
8 001000 110111 111000 001000
आप आसानी से देख सकते हैं कि कॉलम 2 और 4 का परिणाम कॉलम 2 जैसा ही होगा।
यदि आप इस चार्ट से गायब अन्य मूल्यों को देखते हैं, तो आप देख सकते हैं कि यह किसी भी चीज़ के लिए क्यों नहीं है, लेकिन दो की शक्तियाँ:
n base 2 ~n ~n+1 (-n) n&-n
1 000001 111110 111111 000001
2 000010 111101 111110 000010
3 000011 111100 111101 000001
4 000100 111011 111100 000100
5 000101 111010 111011 000001
6 000110 111001 111010 000010
7 000111 111000 111001 000001
8 001000 110111 111000 001000
n & -n होगा (n> 0 के लिए) केवल 1 बिट सेट है, और वह बिट n में सबसे कम महत्वपूर्ण सेट बिट होगा। सभी संख्याओं के लिए जो दो की शक्तियां हैं, सबसे कम महत्वपूर्ण सेट बिट एकमात्र सेट बिट है। अन्य सभी नंबरों के लिए, एक से अधिक बिट सेट हैं, जिनमें से केवल सबसे कम परिणाम में सेट किया जाएगा।
यह 2 की शक्तियों और उनके दो के पूरक की संपत्ति है ।
उदाहरण के लिए, 8 लें:
8 = 0b00001000
-8 = 0b11111000
दो के पूरक की गणना:
Starting: 0b00001000
Flip bits: 0b11110111 (one's complement)
Add one: 0b11111000
AND 8 : 0b00001000
2 की शक्तियों के लिए, केवल एक बिट का गठन किया जाएगा ताकि जोड़ने n कारण होगा वें 2 की बिट n स्थापित किया जाना (एक n करने के लिए ले जा रहा रखता वें बिट)। फिर जब आप AND
दो नंबर लेते हैं, तो आपको मूल वापस मिल जाता है।
उन संख्याओं के लिए जो 2 की शक्तियां नहीं हैं, अन्य बिट्स फ़्लिप नहीं होंगे, इसलिए AND
मूल संख्या प्राप्त नहीं होगी ।
बस, यदि n 2 की शक्ति है जिसका अर्थ है कि केवल एक बिट 1 पर सेट है और अन्य 0 हैं:
00000...00001 = 2 ^ 0
00000...00010 = 2 ^ 1
00000...00100 = 2 ^ 2
00000...01000 = 2 ^ 3
00000...10000 = 2 ^ 4
and so on ...
और क्योंकि -n
एक 2 का पूरक है n
(इसका मतलब है कि केवल बिट जो 1 शेष है जैसा कि वह है और उस बिट के बाईं ओर बिट 1 हैं जो वास्तव में कोई बात नहीं है क्योंकि AND ऑपरेटर का परिणाम &
0 होगा यदि दो बिट्स में से एक शून्य है):
000000...000010000...00000 <<< n
&
111111...111110000...00000 <<< -n
--------------------------
000000...000010000...00000 <<< n