2009-01-20 24 views
5

में कनवर्ट करने का सबसे प्रभावी तरीका मेरे पास 32 बिट बीसीडी वैल्यू (दो यूंट हिस्सों में आपूर्ति) को एक बाइनरी वैल्यू में बदलने के लिए नीचे दिया गया कोड है।बीसीडी को बाइनरी

0x99999999 का अधिकतम मूल्य बनाने के लिए आपूर्ति किए गए मान 0x9999 तक हो सकते हैं।

क्या यह हासिल करने के लिए कोई बेहतर (यानी तेज) तरीका है?

/// <summary> 
    /// Convert two PLC words in BCD format (forming 8 digit number) into single binary integer. 
    /// e.g. If Lower = 0x5678 and Upper = 0x1234, then Return is 12345678 decimal, or 0xbc614e. 
    /// </summary> 
    /// <param name="lower">Least significant 16 bits.</param> 
    /// <param name="upper">Most significant 16 bits.</param> 
    /// <returns>32 bit unsigned integer.</returns> 
    /// <remarks>If the parameters supplied are invalid, returns zero.</remarks> 
    private static uint BCD2ToBin(uint lower, uint upper) 
    { 
     uint binVal = 0; 

     if ((lower | upper) != 0) 
     { 
      int shift = 0; 
      uint multiplier = 1; 
      uint bcdVal = (upper << 16) | lower; 

      for (int i = 0; i < 8; i++) 
      { 
       uint digit = (bcdVal >> shift) & 0xf; 

       if (digit > 9) 
       { 
        binVal = 0; 
        break; 
       } 
       else 
       { 
        binVal += digit * multiplier; 
        shift += 4; 
        multiplier *= 10; 
       } 
      } 
     } 

     return binVal; 
    } 
+0

मेरे लिए बहुत अच्छा लग रहा है लानत। – Spence

+1

अगर हम केवल 16 बिट्स का प्रतिनिधित्व करते हैं तो यह दो यूट्स के बजाय दो यूंट्स क्यों लेता है? –

उत्तर

2

आपका कोड अपेक्षाकृत जटिल लगता है; क्या आपको विशिष्ट त्रुटि जांच की आवश्यकता है?

अन्यथा, आप बस निम्नलिखित कोड है जो धीमी नहीं होना चाहिए इस्तेमाल कर सकते हैं, वास्तव में, यह ज्यादातर एक ही है:

uint result = 0; 
uint multiplier = 1; 
uint value = lo | hi << 0x10; 

while (value > 0) { 
    uint digit = value & 0xF; 
    value >>= 4; 
    result += multiplier * digit; 
    multiplier *= 10; 
} 
return result; 
1

मुझे लगता है कि आप पाश उतारना सकता है:

value = (lo  & 0xF); 
value+= ((lo>>4) & 0xF) *10; 
value+= ((lo>>8) & 0xF) *100; 
value+= ((lo>>12)& 0xF) *1000; 
value+= (hi  & 0xF) *10000; 
value+= ((hi>>4 & 0xF) *100000; 
value+= ((hi>>8) & 0xF) *1000000; 
value+= ((hi>>12)& 0xF) *10000000; 

और अगर आप इस तरह अवैध बीसीडी अंक के लिए जाँच कर सकते हैं:

invalid = lo & ((lo&0x8888)>>2)*3 

यह एक गैर शून्य valu को अमान्य सेट ई अगर कोई एकल हेक्स अंक> 9.

+0

यह काफी काम नहीं करता है। जब आप लूप को अनलॉक करते हैं, तो आपको "मान >> = 4;" याद रखना होगा – epotter

6

यदि आप लूप को अनलॉक करते हैं, तो बिट शिफ्ट रखना याद रखें।

value = (lo  & 0xF); 
value += ((lo >> 4) & 0xF) * 10; 
value += ((lo >> 8) & 0xF) * 100; 
value += ((lo >> 12) & 0xF) * 1000; 
value += (hi  & 0xF) * 10000; 
value += ((hi >> 4) & 0xF) * 100000; 
value += ((hi >> 8) & 0xF) * 1000000; 
value += ((hi >> 12) & 0xF) * 10000000; 
+0

इसे एशेलली के उत्तर – epotter

+0

के साथ जोड़ा जाना चाहिए कृपया थोड़ा twiddling ऑपरेटरों के आसपास माता-पिता रखो - उनके लिए ऑपरेटर प्राथमिकता ज्यादातर लोगों के लिए बहुत भ्रमित है। –

+0

अच्छी कॉल। यह इसे और अधिक पठनीय बनाता है। – epotter

8

यदि आपके पास 39,322 तत्व सरणी के लिए अतिरिक्त स्थान है, तो आप हमेशा मूल्य को देख सकते हैं।

+0

कच्ची गति के लिए एक लुक-अप टेबल निश्चित रूप से जीतने जा रही है। – ScottS

+0

अब तक का सबसे तेज़ समाधान। (उसने इसके लिए पूछा) – GvS

0

बेशक, एक और अधिक कुशल विधि है। यह सिर्फ पाठ्यक्रम के एक उदाहरण है, तो आप एक सबक ^^

function bcd_to_bin ($bcd) {  
$mask_sbb = 0x33333333;   
$mask_msb = 0x88888888; 
$mask_opp = 0xF; 

for($i=28;$i;--$i) {    
    $mask_msb <<= 1; 
    $mask_opp <<= 1; 
    $mask_sbb <<= 1; 

    for($j=0;$j<$i;$j+=4) { 
     $mask_opp_j = $mask_opp << $j; 

     if ($bcd & $mask_msb & $mask_opp_j) { 
      $bcd -= $mask_sbb & $mask_opp_j; 
     } 
    } 
} 

return $bcd;  

}

2

के रूप में यह धुन कर सकते हैं इस प्रयास करें:

public static int bcd2int(int bcd) { 
    return int.Parse(bcd.ToString("X")); 
} 
0
public static uint BCDToNum(int num) 
{ 
    return uint.Parse(num.ToString(), System.Globalization.NumberStyles.HexNumber); 
}