2013-09-06 4 views
7

मुझे char सरणी के रूप में प्रदर्शित बिट्ससेट्स के बीच हैमिंग दूरी की गणना करने की आवश्यकता है। यह एक कोर ऑपरेशन है, इसलिए इसे यथासंभव तेज़ होना चाहिए।बिटवाई ऑपरेशंस। क्या यह कोड सुरक्षित और पोर्टेबल है?

const int N = 32; // 32 always 

// returns the number of bits that are ones in a char 
int countOnes_uchar8(unsigned char v); 

// pa and pb point to arrays of N items 
int hamming(const unsigned char *pa, const unsigned char *pb) 
{ 
    int ret = 0; 
    for(int i = 0; i < N; ++i, ++pa, ++pb) 
    { 
    ret += countOnes_uchar8(*pa^*pb); 
    } 
    return ret; 
} 

रूपरेखा के बाद, मैंने देखा है कि int रों पर काम तेजी से होता है, तो मैं ने लिखा है:: मैं कुछ इस तरह है

const int N = 32; // 32 always 

// returns the number of bits that are ones in a int of 32 bits 
int countOnes_int32(unsigned int v); 

// pa and pb point to arrays of N items 
int hamming(const unsigned char *pa, const unsigned char *pb) 
{ 
    const unsigned int *qa = reinterpret_cast<const unsigned int*>(pa); 
    const unsigned int *qb = reinterpret_cast<const unsigned int*>(pb); 

    int ret = 0; 
    for(int i = 0; i < N/sizeof(unsigned int); ++i, ++qa, ++qb) 
    { 
    ret += countOnes_int32(*qa^*qb); 
    } 
    return ret; 
} 

प्रश्न

1) कि है unsigned char * से unsigned int * सुरक्षित से?

2) मैं 32-बिट मशीन पर काम करता हूं, लेकिन मैं 64-बिट मशीन पर कोड को काम करना चाहता हूं। क्या sizeof(unsigned int) दोनों मशीनों में 4 लौटाता है, या यह 64-बिट एक पर 8 है?

3) यदि sizeof(unsigned int) 64-बिट मशीन में 4 लौटा, तो मैं long long के साथ 64-बिट प्रकार पर कैसे काम कर पाऊंगा?

+0

आप अनवधि पूर्णांक का अधिकतम आकार, केवल न्यूनतम गारंटी नहीं कर सकते हैं। – OllieB

+3

आप की गणना कैसे करते हैं? मैंने पाया कि बिट्स :: गिनती कुछ सिस्टम पर अपने कोड से तेज हो सकती है, क्योंकि यह विशेष सीपीयू निर्देश का लाभ लेती है। –

+1

'std :: bitset' को पहले से ही अनुकूलित किया जाना चाहिए (और गिनने के लिए)। इसे फिर से क्यों करें? –

उत्तर

11

क्या unsigned char * से unsigned int * सुरक्षित है?

औपचारिक रूप से, यह अपरिभाषित व्यवहार देता है। व्यावहारिक रूप से, यह पर किसी भी प्लेटफ़ॉर्म पर काम करेगा यदि पॉइंटर unsigned int के लिए उचित रूप से गठबंधन किया गया है। कुछ प्लेटफार्मों पर, यह संरेखण गलत होने पर विफल हो सकता है, या खराब प्रदर्शन कर सकता है।

क्या sizeof(unsigned int) दोनों मशीनों में 4 लौटाता है, या यह 64-बिट एक पर 8 है?

यह निर्भर करता है। कुछ प्लेटफ़ॉर्म में 64-बिट int है, और कुछ में 32-बिट है। प्लेटफॉर्म पर ध्यान दिए बिना uint64_t का उपयोग करना संभवतः होगा; 32-बिट प्लेटफ़ॉर्म पर, आप प्रभावी रूप से लूप को अनलॉक कर रहे होंगे (प्रति पुनरावृत्ति के दो 32-बिट मानों को प्रोसेस करना), जो मामूली सुधार दे सकता है।

मैं long long के साथ 64-बिट प्रकार पर कैसे काम कर पाऊंगा?

uint64_t, यदि आपके पास सी ++ 11 या सी 99 लाइब्रेरी है। long long कम से कम 64 बिट्स है, लेकिन पूर्व-2011 कार्यान्वयन पर मौजूद नहीं हो सकता है।

+0

'' * qa^* qb'' 'int'' को पढ़ता है जहां से सूचक' '' 'के लिए इंगित करता है। यदि आप बाइट्स की सरणी एक्सेस कर रहे हैं तो कोड असफल हो जाएगा। –

+0

"अगर सूचक को हस्ताक्षरित int के लिए उपयुक्त रूप से गठबंधन किया गया है"। क्या इसका मतलब यह है कि अगर मैं 'qa + = 1' लिखता हूं, 'आकार (हस्ताक्षरित int)' बाइट्स को आगे बढ़ाने के बजाय, यह बाइट्स की एक अलग राशि अग्रिम कर सकता है? – ChronoTrigger

+0

@ सर्गेईके .: आपका क्या मतलब है, "असफल"? जैसा कि मेरा जवाब कहता है, यह औपचारिक रूप से अपरिभाषित व्यवहार देता है, लेकिन उचित संरेखण दिए गए अधिकांश प्लेटफॉर्म पर आवश्यकतानुसार काम करेगा। –

2

1) नहीं, यह सुरक्षित/पोर्टेबल नहीं है, यह अपरिभाषित व्यवहार है। ऐसे सिस्टम हैं जहां char एक बाइट से बड़ा है और कोई गारंटी नहीं है कि चार सूचक सही ढंग से गठबंधन हैं।

2) sizeof(int) सिद्धांत में 64 बिट मशीन पर कुछ भी हो सकता है। अभ्यास में, यह या तो 4 या 8.

3) long long 64 बिट्स की संभावना है लेकिन वहां कोई गारंटी नहीं है। यदि आप गारंटी चाहते हैं, तो uint64_t का उपयोग करें। हालांकि, आपके विशिष्ट एल्गोरिदम के लिए मुझे नहीं लगता कि sizeof() डेटा खंड क्यों मायने रखता है।

बजाय, वे कहीं अधिक पोर्टेबल कोड के लिए उपयुक्त हैं stdint.h में प्रकार का उपयोग पर विचार करें। चार, int या लंबे समय के बजाय, का उपयोग करें। यह संकलक को पोर्टेबल तरीके से आपके लिए सबसे तेज़ पूर्णांक चुनने देगा।

एक sidenote के रूप में, आप एक लुकअप तालिका के रूप में "countOnes" को लागू करने 4, 8 या 32 बिट स्तर पर काम कर रहा है, क्या आपके सिस्टम के लिए सबसे इष्टतम है पर निर्भर करता है पर विचार करना चाहिए। यह प्रोग्राम आकार में वृद्धि करेगा लेकिन निष्पादन समय को कम करेगा। शायद अनुकूली लुकअप टेबल के कुछ रूप को लागू करने का प्रयास करें जो sizeof(uint_fast8_t) पर निर्भर करता है।

+0

'char' एक बाइट से कभी बड़ा नहीं है। एक बाइट 8 बिट्स से बड़ा हो सकता है, यद्यपि। –

+0

@ कार्नलोरम कंप्यूटर विज्ञान 8 बिट्स के संग्रह के रूप में एक बाइट परिभाषित करता है। न तो सी भाषा और न ही कुछ अप्रचलित, अस्पष्ट CPU प्रकार इसे बदल सकता है। और 8 से अधिक बिट्स के साथ कुछ भी एक बाइट से अधिक परिभाषा है। – Lundin

+0

कड़ाई से बोलते हुए, इनमें से कोई भी सही नहीं है, या तो। मैं निश्चित रूप से सहमत हूं कि यह नापसंद है। http://en.wikipedia.org/wiki/Byte। बहुत सारे डीएसपी हैं जिनमें 16-बिट बाइट हैं इसलिए यह शायद ही अस्पष्ट है। CHAR_BIT मैक्रो मौजूद है, और यह भी कारण है कि भाषा मानक सामान्य रूप से बाइट शब्द से बचने के लिए कड़ी मेहनत करता है। –

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