2012-03-22 6 views
9

अगर मैं सरणी है:क्या एक बाइट सरणी पर एक सही परिपत्र सा बदलाव करने के लिए सबसे तेज़ तरीका है

{01101111,11110000,00001111} // {111, 240, 15} 

एक 1 बिट बदलाव के लिए परिणाम है:

{10110111,11111000,00000111} // {183, 248, 7} 

सरणी आकार तय नहीं है, और स्थानांतरण 1 से 7 समावेशी होगा। वर्तमान में मेरे पास निम्न कोड है (जो ठीक काम करता है):

private static void shiftBitsRight(byte[] bytes, final int rightShifts) { 
    assert rightShifts >= 1 && rightShifts <= 7; 

    final int leftShifts = 8 - rightShifts; 

    byte previousByte = bytes[0]; // keep the byte before modification 
    bytes[0] = (byte) (((bytes[0] & 0xff) >> rightShifts) | ((bytes[bytes.length - 1] & 0xff) << leftShifts)); 
    for (int i = 1; i < bytes.length; i++) { 
     byte tmp = bytes[i]; 
     bytes[i] = (byte) (((bytes[i] & 0xff) >> rightShifts) | ((previousByte & 0xff) << leftShifts)); 
     previousByte = tmp; 
    } 
} 

क्या मेरे वर्तमान दृष्टिकोण से इसे हासिल करने का कोई तेज़ तरीका है?

+3

मुझे लगता है कि 'लम्बे पहले' में समूहांकन प्रदर्शन के लिए फायदेमंद होगा। –

+0

यदि यह ग्राफिक्स के लिए है, तो इसके बारे में सोचने का एक और विकल्प रन-लम्बा एन्कोडेड प्रारूप का उपयोग करना है। फिर स्थानांतरित करने के लिए लाइन के बीच में सभी रन लम्बाई बदलनी पड़ेगी। – BitBank

+1

'लंबा' प्रदर्शन में सुधार कर सकता है, लेकिन यह मशीन से मशीन में भिन्न होगा। (कभी-कभी 'int' बेहतर होगा।) –

उत्तर

4

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

+3

डाउनवॉटर नहीं, समझाओ? (यदि ओपी के प्रश्न के लिए कोई भी सामान्य जवाब था तो मैं बहुत आश्चर्यचकित हूं कि इससे अधिक विशिष्ट था।) –

+0

+1, पूरी तरह से सच –

0

आप देशांतर को यह सामान्यीकरण और एक से अधिक बिट पारी अगर आप

// for a 1-bit rightshift: 
// first rotate each byte right by one 
for (i = 0; i < n; i++) b[i] = rotr(b[i], 1); 
// get rightmost bit 
bit = b[n-1] & 0x80; 
// copy high order bit from adjacent byte 
for (i = n; --i >= 1;){ 
    b[i] &= 0x7f; 
    b[i] |= (b[i-1] & 0x80); 
} 
// put in the rightmost bit on the left 
b[0] = (b[0] & 0x7f) | bit; 

संभालने rotr परिभाषित किया गया है की तरह कर सकते हैं।

1

जिन्हें आप कर सकते में से एक byte[a]>>>b

साथ (byte[a]&0xff)>>b की जगह इसके अलावा, आप &0xff की जरूरत नहीं है जब आप स्थानांतरण छोड़ दिया जाता है है।

हालांकि इससे कोई फर्क नहीं पड़ता, या तो tmp पर अंतिम जोड़ना या लूप से घोषणा को स्थानांतरित करना थोड़ा सा मदद कर सकता है।

एक और बात की कोशिश कर सकते है:

int tmp=bytes[bytes.length-1]; 
for (int i = bytes.length-2; i >=0; i--) { 
    tmp=(tmp<<8)|bytes[i]; 
    bytes[i] = (byte) (tmp>>>rightShifts); 
} 

तो फिर तुम बाइट्स [bytes.length-1] बाद में हल।

लूप के विपरीत यह भी मदद कर सकता है अगर आप अंधविश्वास वाले हैं। मैंने इसे पहले देखा है। पास प्रति

लूप विश्लेषण:

तुम्हारा: 3 कार्य, दो पालियों, एक या एक से, एक डाली।

मेरा: 2 असाइनमेंट, दो बदलाव, एक या एक कलाकार।

+0

'(बाइट [ए] और 0xff) >> बी' और' बाइट [ए] >>> बी 'बराबर नहीं हैं! पूर्व में, वांछित परिणाम उत्पन्न करने वाले उच्च बाइट को हटाने के बाद बाईं ओर 'int' को बढ़ावा दिया जाता है। बाद में, पदोन्नति होती है, फिर एक हस्ताक्षरित शिफ्ट होती है, इसलिए 'ए' के बाईं ओर बिट्स' ए' का संकेत बिट होगा, फिर 0 की 'बी' संख्या होगी। –

0

उपयोग ByteBuffer.wrap एक बफर है कि आपके byte[] लपेटता और फिर ByteBuffer.asLongBuffer() का प्रयोग कर एक राय यह है कि आप निकालने और के रूप में @NiklasB ने सुझाव दिया हेरफेर long रों करने की अनुमति देता प्राप्त करने के लिए। इस प्रकार बिट्स के बड़े हिस्से को स्थानांतरित करने की हार्डवेयर की क्षमता का लाभ उठाते हैं।

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