2009-01-20 79 views
5

我有下面的代碼將32位BCD值(以兩個半角提供)轉換爲uint二進制值。將BCD轉換爲二進制的最有效方法

提供的值可以高達0x9999,以形成最大值0x99999999。

有沒有更好的(即更快)的方式來實現這一目標?

/// <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 2009-01-20 20:38:00

+1

爲什麼需要兩個提示而不是ushorts,如果每個只代表16位? – 2009-01-20 20:38:44

回答

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; 

您可以檢查無效的BCD數字,如下所示:

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

這會將無效值設置爲非零值e如果任何單個十六進制數字大於9.

+0

這不起作用。當你展開循環時,你必須記住「value >> = 4;」 – epotter 2009-01-21 02:27:39

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

這應該與AShelly的回答結合使用 – epotter 2009-01-21 02:34:19

8

如果您有足夠的空間來存放39,322個元素的數組,您可以隨時查看數值。

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); 
} 
相關問題