2009-05-04 15 views
8

मैं सकारात्मक पूर्णांक संख्या के लिए 3 आधार निरूपण है:कुशलतापूर्वक सी में हेक्स, द्विआधारी, और दशमलव के बीच परिवर्तित/C++

  1. दशमलव, अहस्ताक्षरित लंबे चर में (जैसे अहस्ताक्षरित लंबे int NumDec = 200)।
  2. हेक्स, स्ट्रिंग चर में (जैसे स्ट्रिंग NumHex = "सी 8")
  3. बाइनरी, स्ट्रिंग चर में (जैसे स्ट्रिंग NumBin = "11,001,000")

मैं करने में सक्षम होना चाहता हूँ सबसे प्रभावी तरीके से सभी 3 प्रस्तुतिकरणों में संख्याओं के बीच कनवर्ट करें। अर्थात। निम्नलिखित 6 कार्यों को लागू करने के लिए:

unsigned long int Binary2Dec(const string & Bin) {} 
unsigned long int Hex2Dec(const string & Hex) {} 
string Dec2Hex(unsigned long int Dec) {} 
string Binary2Hex(const string & Bin) {} 
string Dec2Binary(unsigned long int Dec) {} 
string Hex2Binary(const string & Hex) {} 

उनमें से प्रत्येक के लिए सबसे कुशल दृष्टिकोण क्या है? मैं सी और सी ++ का उपयोग कर सकता हूं, लेकिन बढ़ावा नहीं देता हूं।

संपादित करें: "दक्षता" से मेरा मतलब समय दक्षता: सबसे कम निष्पादन समय।

+2

आप पहले दो फ़ंक्शन नाम हैं बेहद भ्रामक हैं। आप एक दशमलव प्रतिनिधित्व वापस नहीं कर रहे हैं। आप एक अपरिभाषित, अपारदर्शी (जब तक आप कुछ कार्यान्वयन-परिभाषित नहीं करते) आंतरिक प्रतिनिधित्व के साथ एक हस्ताक्षरित लंबे समय तक लौट रहे हैं। –

+0

आप फ़ंक्शन नामों का प्रस्ताव क्या करेंगे? –

+1

Binary2Int और Hex2Int एक बहुत अधिक समझ में आता है बेशक इन कार्यों ग पुस्तकालय में strtol साथ अनावश्यक हैं – jmucchiello

उत्तर

7

जैसा कि अन्य ने बताया है, मैं sscanf(), printf() और/या strtoul() से शुरू करूंगा। वे अधिकतर अनुप्रयोगों के लिए पर्याप्त तेज़ होते हैं, और उनमें बग होने की संभावना कम होती है। हालांकि, मैं कहूंगा कि ये फ़ंक्शंस अपेक्षाकृत अधिक सामान्य हैं, क्योंकि उन्हें गैर-ASCII वर्ण सेटों से निपटना होगा, किसी भी आधार में और आगे के प्रतिनिधित्व के साथ। कुछ डोमेन के लिए लाइब्रेरी फ़ंक्शंस को हरा करना संभव है।

1) कुछ अनुप्रयोगों/डोमेन निश्चित संख्या बहुत अक्सर दिखाई देते हैं, उदाहरण के शून्य, 100, 200, 19.95 के लिए,:

तो, पहले मापने, और अगर इन रूपांतरण के प्रदर्शन वास्तव में एक मुद्दा है, तो है इतना आम हो सकता है कि इस तरह की संख्याओं को if() कथन के समूह के साथ बदलने के लिए अपने कार्यों को अनुकूलित करने के लिए समझदारी हो जाती है, और फिर जेनेरिक लाइब्रेरी फ़ंक्शंस पर वापस आती है। 2) तालिका तालिका का उपयोग करें यदि सबसे आम 100 संख्याएं हैं, और फिर लाइब्रेरी फ़ंक्शन पर वापस आती हैं। याद रखें कि बड़ी टेबल आपके कैश में फिट नहीं हो सकती हैं और साझा पुस्तकालयों के लिए एकाधिक संकेतों की आवश्यकता हो सकती है, इसलिए यह सुनिश्चित करने के लिए कि आप प्रदर्शन कम नहीं कर रहे हैं, इन चीजों को ध्यान से मापें।

आप बूस्ट लेक्सिकल_कास्ट फ़ंक्शंस को भी देखना चाहते हैं, हालांकि मेरे अनुभव में उत्तरार्द्ध अपेक्षाकृत पुराने पुराने कार्यों की तुलना में अपेक्षाकृत अपेक्षाकृत हैं।

कठिन लोगों ने यह कहा है कि यह दोहराए जाने के लायक है: इन रूपांतरणों को अनुकूलित न करें जब तक कि आपके पास सबूत न हो कि वे एक समस्या है। यदि आप अनुकूलित करते हैं, तो यह सुनिश्चित करने के लिए अपने नए कार्यान्वयन को मापें और सुनिश्चित करें कि आपके पास अपने संस्करण के लिए यूनिट परीक्षणों का एक टन है, क्योंकि आप बग पेश करेंगे :-(

2

यह उस पर निर्भर करता है कि आप किसके लिए अनुकूलित कर रहे हैं, आप "कुशल" से क्या मतलब रखते हैं? क्या यह महत्वपूर्ण है कि रूपांतरण तेजी से हो, थोड़ी मेमोरी, थोड़ा प्रोग्रामर समय, कम WTFs कोड पढ़ने वाले अन्य प्रोग्रामर से, या क्या?

पठनीयता और कार्यान्वयन की आसानी के लिए, आपको कम से कम Dec2Hex() और Dec2Binary() दोनों को strotul() पर कॉल करके लागू करना चाहिए। यह उन्हें एक-लाइनर में बनाता है, जो शब्द की उपरोक्त व्याख्याओं में से कम से कम कुछ के लिए बहुत ही कुशल है।

+0

"दक्षता" से मेरा मतलब समय दक्षता: सबसे कम निष्पादन समय। इसे स्पष्ट करने के लिए धन्यवाद। –

1

बहुत ज्यादा एक होमवर्क समस्या की तरह लगता है, लेकिन क्या बिल्ली ...

संक्षिप्त उत्तर लंबे int से परिवर्तित अपने तार दो देखने तालिकाओं का उपयोग करने के लिए है। प्रत्येक तालिका में 256 प्रविष्टियां होनी चाहिए। एक हेक्स स्ट्रिंग के लिए बाइट को मानचित्र करता है: 0 -> "00", 1 -> "01", आदि। अन्य मानचित्र बाइट को थोड़ा स्ट्रिंग: 0 -> "00000000", 1 -> "00000001"।

फिर आपके लंबे int में प्रत्येक बाइट के लिए आपको सही स्ट्रिंग को देखना होगा, और उन्हें संयोजित करना होगा।

स्ट्रिंग्स से लंबे समय तक कनवर्ट करने के लिए आप केवल हेक्स स्ट्रिंग और बिट स्ट्रिंग को प्रत्येक वर्ण के संख्यात्मक मान को 16 या 2 की उचित शक्ति से गुणा करके और परिणामों को संक्षेप में परिवर्तित करके दशमलव संख्या में परिवर्तित कर सकते हैं।

संपादित करें: आप सही स्ट्रिंग को खोजने के लिए बाइनरी खोज करके बैकवर्ड रूपांतरण के लिए समान लुकअप टेबल का भी उपयोग कर सकते हैं। यह लॉग (256) = 8 आपके तारों की तुलना करेगा। दुर्भाग्यवश मेरे पास विश्लेषण करने का समय नहीं है कि तारों की तुलना करना गुणा करने और पूर्णांक जोड़ने से कहीं अधिक तेज़ होगा।

+0

स्ट्रिंग्स के लंबे रूपांतरण के संबंध में: क्या यह strotul() से तेज़ी से काम करेगा? –

+0

पता नहीं ... इसे आज़माएं। – Dima

4

मैं केवल sprintf और sscanf का उपयोग करने का सुझाव दूंगा।

इसके अलावा, यदि आप रुचि रखते हैं कि यह कैसे कार्यान्वित किया गया है तो आप source codeglibc, the GNU C Library के लिए देख सकते हैं।

+0

क्या यह अन्य समाधानों की तुलना में धीमी गति से काम नहीं करेगा? –

+3

दो उत्तर: 1. सभी समाधानों का परीक्षण करें और देखें कि कौन सा तेज़ है। 2. सी मानक लाइब्रेरी में कोड को आम तौर पर विशेष रूप से लिखित और अत्यधिक अनुकूलित किया जाता है - इस तरह की समस्याएं पूरी तरह से मानक पुस्तकालय मौजूद हैं, इसलिए प्रोग्रामर को बेहद आम समस्याओं के लिए विशेषज्ञ रूप से लिखित समाधान तक पहुंच है और उन्हें जाना नहीं है और लगातार पहिया को फिर से शुरू करें। –

+0

यह भी याद रखें कि स्प्रिंटफ और एसएसकेएनएफ का व्यापक रूप से परीक्षण किया गया है, और आपके पास रूपांतरण करने की कोशिश करने वाली छोटी छोटी चीजें नहीं हो सकती हैं। –

0

प्रारूप के रूप में प्रारूप को लेने के लिए मैक्रो का उपयोग क्यों न करें। यदि आप कम से कम सी में हैं।

#define TO_STRING(string, format, data) \ 
sprintf(string, "##format##", data) 
// Int 
TO_STRING(buf,%d,i); 
// Hex (Two char representation) 
TO_STRING(buf,%02x,i); 
// Binary 
TO_STRING(buf,%b,i); 

या आप सीधे स्पिंटफ का उपयोग कर सकते हैं: या आपके पास एकाधिक मैक्रो हो सकते हैं।

#define INT_STRING(buf, data) \ 
sprintf(buf, "%d", data) 
#define HEX_STRING(buf, data) \ 
sprintf(buf, "%x", data) 
#define BIN_TO_STRING(buf, data) \ 
sprintf(buf, "%b", data) 

BIN_TO_STRING(loc_buf, my_bin); 
3

इन दिनचर्या को इतना समय-समय पर क्यों होना चाहिए? उस तरह का दावा हमेशा मुझे आश्चर्य करता है। क्या आप सुनिश्चित हैं कि स्ट्रैटोल() जैसे स्पष्ट रूपांतरण विधियां बहुत धीमी हैं, या आप बेहतर कर सकते हैं? सिस्टम फ़ंक्शन आमतौर पर बहुत ही कुशल होते हैं। वे कभी-कभी सामान्यता और त्रुटि-जांच का समर्थन करने के लिए धीमे होते हैं, लेकिन आपको यह समझने की आवश्यकता है कि त्रुटियों के साथ क्या करना है। यदि bin तर्क में '0' और '1' के अलावा वर्ण हैं, तो फिर क्या? निरस्त करें? भारी त्रुटियों का प्रचार करें?

आंतरिक प्रतिनिधित्व का प्रतिनिधित्व करने के लिए आप "दिसंबर" का उपयोग क्यों कर रहे हैं? स्ट्रिंग प्रस्तुतियों को संदर्भित करने के लिए दिसंबर, हेक्स और बिन का उपयोग किया जाना चाहिए। unsigned long के बारे में कुछ भी दशमलव नहीं है। क्या आप दशमलव में संख्या दिखाते हुए तारों से निपट रहे हैं? यदि नहीं, तो आप यहां लोगों को भ्रमित कर रहे हैं और कई और भ्रमित होने जा रहे हैं।

बाइनरी और हेक्स टेक्स्ट प्रारूपों के बीच परिवर्तन लुकअप टेबल के साथ जल्दी और कुशलता से किया जा सकता है, लेकिन दशमलव पाठ प्रारूप से जुड़ी कुछ भी अधिक जटिल होगी।

1

चलिए एक पल के लिए आधे कार्य के बारे में सोचें - एक स्ट्रिंग-ized बेस एन से हस्ताक्षरित लंबे समय तक कनवर्ट करना, जहां एन 2 की शक्ति है (बाइनरी के लिए आधार 2 और हेक्स के लिए आधार 16)।

यदि आपका इनपुट सचेत है, तो यह काम तुलना, एक घटा, एक शिफ्ट और प्रति अंक से अधिक कुछ नहीं है। यदि आपका इनपुट सचेत नहीं है, तो, वह वही है जहां यह बदसूरत हो जाता है, है ना? रूपांतरण superfast करना मुश्किल नहीं है। सभी परिस्थितियों में इसे अच्छी तरह से करना चुनौती है।

unsigned long PowerOfTwoFromString(char *input, int shift) 
{ 
    unsigned long val = 0; 
    char upperLimit = 'a' + (1 << shift) 
    while (*input) { 
     char c = tolower(*input++); 
     unsigned long digit = (c > 'a' && c < upperLimit) ? c - 'a' + 10 : c - '0'; 
     val = (val << shift) | digit; 
    } 
    return val; 
} 

#define UlongFromBinaryString(str) PowerOfTwoFromString(str, 1) 
#define UlongFromHexString(str) PowerOfTwoFromString(str, 4) 

देखें है कि कितना आसान:

तो चलो मान लेते हैं कि अपने इनपुट समझदार है करते हैं, तो आपके रूपांतरण के दिल है? और यह गैर-सना इनपुट पर असफल हो जाएगा। आपका अधिकांश काम आपके इनपुट कोने में प्रदर्शन करने जा रहा है, प्रदर्शन नहीं।

अब, यह कोड दो स्थानांतरण की शक्ति का लाभ उठाता है। बेस 4, बेस 8, बेस 32 इत्यादि तक विस्तार करना आसान है। यह दो अड्डों की गैर-शक्ति पर काम नहीं करेगा। उन लोगों के लिए, आपके गणित को बदलना है। आपको

val = (val * base) + digit 

जो संचालन के इस सेट के लिए अवधारणात्मक रूप से समान है। आधार द्वारा गुणा शिफ्ट के बराबर होने जा रहा है। तो मैं इसके बजाय एक पूरी तरह से सामान्य दिनचर्या का उपयोग करने की संभावना होगी। और इनपुट को स्वच्छ करते समय कोड को स्वच्छ करें। और उस समय, स्ट्रेटोल शायद आपकी सबसे अच्छी शर्त है। स्ट्रेटल के a version का लिंक यहां दिया गया है। लगभग सभी काम बढ़त की स्थिति को संभालने में कामयाब रहे हैं - आपको उस पर ध्यान देना चाहिए जहां आप ऊर्जा को केंद्रित करना चाहिए: सही, लचीला कोड। बिट बदलावों का उपयोग करने के लिए बचत कम बचत पर दुर्घटनाग्रस्त नहीं होने की बचत की तुलना में न्यूनतम होने जा रही है।

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