Java Language
बिट मैनिपुलेशन
खोज…
टिप्पणियों
C / C ++ के विपरीत, अंतर्निहित मशीन हार्डवेयर के संबंध में जावा पूरी तरह से एंडियन-न्यूट्रल है। आपको डिफ़ॉल्ट रूप से बड़ा या छोटा एंडियन व्यवहार नहीं मिलता है; आपको स्पष्ट रूप से निर्दिष्ट करना होगा कि आपको कौन सा व्यवहार चाहिए।
byte
प्रकार पर हस्ताक्षर किया जाता है, सीमा -128 के साथ +127 तक। बाइट मान को इसके अहस्ताक्षरित समतुल्य में बदलने के लिए, इसे 0xFF के साथ इस तरह से मास्क करें:(b & 0xFF)
।
बिट टुकड़ों के रूप में पैकिंग / अनपैकिंग मान
यह स्मृति प्रदर्शन के लिए एक आदिम मूल्य में कई मूल्यों को संपीड़ित करने के लिए आम है। यह एक चर में विभिन्न जानकारी को पारित करने के लिए उपयोगी हो सकता है।
उदाहरण के लिए, कोई 3 बाइट्स पैक कर सकता है - जैसे RGB में कलर कोड - एक ही इंट में।
मान पैक करना
// Raw bytes as input
byte[] b = {(byte)0x65, (byte)0xFF, (byte)0x31};
// Packed in big endian: x == 0x65FF31
int x = (b[0] & 0xFF) << 16 // Red
| (b[1] & 0xFF) << 8 // Green
| (b[2] & 0xFF) << 0; // Blue
// Packed in little endian: y == 0x31FF65
int y = (b[0] & 0xFF) << 0
| (b[1] & 0xFF) << 8
| (b[2] & 0xFF) << 16;
मूल्यों को खोलना
// Raw int32 as input
int x = 0x31FF65;
// Unpacked in big endian: {0x65, 0xFF, 0x31}
byte[] c = {
(byte)(x >> 16),
(byte)(x >> 8),
(byte)(x & 0xFF)
};
// Unpacked in little endian: {0x31, 0xFF, 0x65}
byte[] d = {
(byte)(x & 0xFF),
(byte)(x >> 8),
(byte)(x >> 16)
};
व्यक्तिगत बिट्स की जाँच, सेटिंग, समाशोधन और टॉगल करना। लंबे समय तक बिट मास्क का उपयोग करना
यह मानते हुए कि हम एक पूर्णांक आदिम के बिट n
को संशोधित करना चाहते हैं, i
(बाइट, शॉर्ट, चार, इंट, या लॉन्ग):
(i & 1 << n) != 0 // checks bit 'n'
i |= 1 << n; // sets bit 'n' to 1
i &= ~(1 << n); // sets bit 'n' to 0
i ^= 1 << n; // toggles the value of bit 'n'
बिट मास्क के रूप में लंबे / इंट / शॉर्ट / बाइट का उपयोग करना:
public class BitMaskExample {
private static final long FIRST_BIT = 1L << 0;
private static final long SECOND_BIT = 1L << 1;
private static final long THIRD_BIT = 1L << 2;
private static final long FOURTH_BIT = 1L << 3;
private static final long FIFTH_BIT = 1L << 4;
private static final long BIT_55 = 1L << 54;
public static void main(String[] args) {
checkBitMask(FIRST_BIT | THIRD_BIT | FIFTH_BIT | BIT_55);
}
private static void checkBitMask(long bitmask) {
System.out.println("FIRST_BIT: " + ((bitmask & FIRST_BIT) != 0));
System.out.println("SECOND_BIT: " + ((bitmask & SECOND_BIT) != 0));
System.out.println("THIRD_BIT: " + ((bitmask & THIRD_BIT) != 0));
System.out.println("FOURTh_BIT: " + ((bitmask & FOURTH_BIT) != 0));
System.out.println("FIFTH_BIT: " + ((bitmask & FIFTH_BIT) != 0));
System.out.println("BIT_55: " + ((bitmask & BIT_55) != 0));
}
}
प्रिंटों
FIRST_BIT: true
SECOND_BIT: false
THIRD_BIT: true
FOURTh_BIT: false
FIFTH_BIT: true
BIT_55: true
जो उस मुखौटा से मेल खाता है जो हमने checkBitMask
पैरामीटर के रूप में पारित किया है: FIRST_BIT | THIRD_BIT | FIFTH_BIT | BIT_55
।
2 की शक्ति व्यक्त करना
पूर्णांक के 2 (2 ^ n) की शक्ति को व्यक्त करने के लिए, एक बिटशिफ्ट ऑपरेशन का उपयोग कर सकता है जो n
को स्पष्ट रूप से निर्दिष्ट करने की अनुमति देता है।
सिंटैक्स मूल रूप से है:
int pow2 = 1<<n;
उदाहरण:
int twoExp4 = 1<<4; //2^4
int twoExp5 = 1<<5; //2^5
int twoExp6 = 1<<6; //2^6
...
int twoExp31 = 1<<31; //2^31
निरंतर मूल्यों को परिभाषित करते समय यह विशेष रूप से उपयोगी होता है जो इसे स्पष्ट करना चाहिए, कि हेक्साडेसिमल या दशमलव मूल्यों का उपयोग करने के बजाय 2 की शक्ति का उपयोग किया जाता है।
int twoExp4 = 0x10; //hexadecimal
int twoExp5 = 0x20; //hexadecimal
int twoExp6 = 64; //decimal
...
int twoExp31 = -2147483648; //is that a power of 2?
2 की अंतर शक्ति की गणना करने के लिए एक सरल विधि होगी
int pow2(int exp){
return 1<<exp;
}
जाँच करना कि क्या कोई संख्या 2 की शक्ति है
यदि एक पूर्णांक x
2 की शक्ति है, तो केवल एक बिट सेट है, जबकि x-1
में उसके बाद के सभी बिट सेट हैं। उदाहरण के लिए: 4
100
और 3
बाइनरी नंबर के रूप में 011
, जो उपरोक्त स्थिति को संतुष्ट करता है। शून्य 2 की शक्ति नहीं है और इसे स्पष्ट रूप से जांचना होगा।
boolean isPowerOfTwo(int x)
{
return (x != 0) && ((x & (x - 1)) == 0);
}
लेफ्ट और राइट शिफ्ट के लिए उपयोग
मान लीजिए, हमारे पास तीन तरह की अनुमतियां हैं, READ , WRITE और EXECUTE । प्रत्येक अनुमति 0 से लेकर 7. तक हो सकती है (मान लें कि 4 बिट संख्या प्रणाली)
परिणाम = पढ़ें पढ़ें (12 बिट संख्या)
परिणाम = 0100 0110 0101 = 4 6 5 (12 बिट संख्या)
हम (12 बिट संख्या) अनुमतियाँ, ऊपर (12 बिट संख्या) पर कैसे प्राप्त कर सकते हैं?
0100 0110 0101
0000 0000 0111 (&)
0000 0000 0101 = 5
तो, यह कैसे हम संसाधन की अनुमति निष्पादित मिल सकता है। अब, क्या हम संसाधन के पढ़ने के लिए अनुमतियां प्राप्त करना चाहते हैं तो क्या होगा?
0100 0110 0101
0111 0000 0000 (&)
0100 0000 0000 = 1024
सही? आप शायद यह मान रहे हैं? लेकिन, अनुमतियाँ 1024 में परिणामित होती हैं। हम संसाधन के लिए केवल READ अनुमतियां प्राप्त करना चाहते हैं। चिंता न करें, इसीलिए हमारे पास शिफ्ट ऑपरेटर थे। यदि हम देखते हैं, तो वास्तविक परिणाम के पीछे READ अनुमतियां 8 बिट्स हैं, इसलिए यदि कुछ शिफ्ट ऑपरेटर लागू करते हैं, जो परिणाम के बहुत दाईं ओर READ अनुमतियाँ लाएगा? अगर हम करते हैं:
0100 0000 0000 >> 8 => 0000 0000 0100 (क्योंकि यह एक सकारात्मक संख्या है, इसलिए इसे 0 के साथ बदल दिया जाता है, यदि आप साइन की परवाह नहीं करते हैं, तो केवल अहस्ताक्षरित सही शिफ्ट ऑपरेटर का उपयोग करें)
अब हमारे पास वास्तव में READ अनुमतियां हैं जो 4 हैं।
अब, उदाहरण के लिए, हम दिया जाता है पढ़ें, लिखें, एक संसाधन के लिए अनुमतियाँ निष्पादित हम इस संसाधन के लिए अनुमतियाँ बनाने के लिए क्या कर सकते हैं?
पहले बाइनरी अनुमतियों का उदाहरण लेते हैं। (अभी भी 4 बिट संख्या प्रणाली संभालने)
READ = 0001
राइट = 0100
EXECUTE = 0110
यदि आप सोच रहे हैं कि हम बस करेंगे:
READ | WRITE | EXECUTE
, आप कुछ हद तक सही हैं लेकिन वास्तव में नहीं। देखिए, अगर हम READ प्रदर्शन करेंगे तो क्या होगा? गलत | निष्पादित
0001 | 0100 | 0110 => 0111
लेकिन अनुमतियों को वास्तव में (हमारे उदाहरण में) 0001 0100 0110 के रूप में दर्शाया जा रहा है
तो, ऐसा करने के लिए, हम जानते हैं कि READ को 8 बिट्स के पीछे रखा गया है, WRITE को 4 बिट्स के पीछे रखा गया है और PERMISSIONS को अंतिम स्थान पर रखा गया है। संसाधन अनुमतियों के लिए उपयोग की जाने वाली संख्या प्रणाली वास्तव में 12 बिट (हमारे उदाहरण में) है। यह (विल) विभिन्न प्रणालियों में भिन्न हो सकता है।
(पढ़ें << 8) | (राइट << 4) | (निष्पादित)
0000 0000 0001 << 8 (READ)
0001 0000 0000 (8 बिट्स द्वारा वाम पारी)
0000 0000 0100 << 4 (WRITE)
0000 0100 0000 (4 बिट्स द्वारा वाम पारी)
0000 0000 0001 (EXECUTE)
अब यदि हम उपरोक्त स्थानांतरण के परिणामों को जोड़ते हैं, तो यह कुछ ऐसा होगा;
0001 0000 0000 (READ)
0000 0100 0000 (WRITE)
0000 0000 0001 (EXECUTE)
0001 0100 0001 (अनुमतियाँ)
java.util.BitSet वर्ग
1.7 के बाद से एक java.util.BitSet वर्ग है जो सरल और उपयोगकर्ता के अनुकूल बिट भंडारण और हेरफेर इंटरफ़ेस प्रदान करता है:
final BitSet bitSet = new BitSet(8); // by default all bits are unset
IntStream.range(0, 8).filter(i -> i % 2 == 0).forEach(bitSet::set); // {0, 2, 4, 6}
bitSet.set(3); // {0, 2, 3, 4, 6}
bitSet.set(3, false); // {0, 2, 4, 6}
final boolean b = bitSet.get(3); // b = false
bitSet.flip(6); // {0, 2, 4}
bitSet.set(100); // {0, 2, 4, 100} - expands automatically
BitSet
Clonable
और Serializable
लागू Clonable
, और हुड के तहत सभी बिट मान long[] words
फ़ील्ड में संग्रहीत किए जाते हैं, जो स्वचालित रूप से फैलता है।
यह संपूर्ण-सेट लॉजिकल ऑपरेशंस and
, or
, xor
, andNot
का भी समर्थन करता है:
bitSet.and(new BitSet(8));
bitSet.or(new BitSet(8));
bitSet.xor(new BitSet(8));
bitSet.andNot(new BitSet(8));
हस्ताक्षरित बनाम अहस्ताक्षरित पारी
जावा में, सभी संख्या के आदिम पर हस्ताक्षर किए जाते हैं। उदाहरण के लिए, एक इंट हमेशा वैल्यू को साइन करने के लिए [-2 ^ 31 - 1, 2 ^ 31] से मानों का प्रतिनिधित्व करता है, नकारात्मक मान के लिए पहला बिट - 1, सकारात्मक के लिए 0।
बेसिक शिफ्ट ऑपरेटर >>
और <<
हस्ताक्षरित ऑपरेटर हैं। वे मूल्य के संकेत का संरक्षण करेंगे।
लेकिन प्रोग्रामर के लिए अहस्ताक्षरित मूल्यों को संग्रहीत करने के लिए संख्याओं का उपयोग करना आम है। एक इंट के लिए, इसका मतलब है कि सीमा को [0, 2 ^ 32 - 1] में स्थानांतरित करना, एक हस्ताक्षरित इंट के साथ दोगुना मूल्य होना।
उन बिजली उपयोगकर्ताओं के लिए, बिना किसी अर्थ के हस्ताक्षर के लिए बिट। यही कारण है कि जावा ने एक बाएं-शिफ्ट ऑपरेटर, >>>
जोड़ा, जो उस साइन बिट की उपेक्षा कर रहा था।
initial value: 4 ( 100)
signed left-shift: 4 << 1 8 ( 1000)
signed right-shift: 4 >> 1 2 ( 10)
unsigned right-shift: 4 >>> 1 2 ( 10)
initial value: -4 ( 11111111111111111111111111111100)
signed left-shift: -4 << 1 -8 ( 11111111111111111111111111111000)
signed right-shift: -4 >> 1 -2 ( 11111111111111111111111111111110)
unsigned right-shift: -4 >>> 1 2147483646 ( 1111111111111111111111111111110)
कोई <<<
क्यों नहीं है?
यह राइट-शिफ्ट की इच्छित परिभाषा से आता है। चूंकि यह बाईं ओर खाली जगहों को भरता है, इसलिए साइन के बिट के बारे में निर्णय लेने का कोई निर्णय नहीं है। परिणामस्वरूप, 2 अलग-अलग ऑपरेटरों की आवश्यकता नहीं है।
इस प्रश्न को और अधिक जवाब के लिए देखें।