2009-01-20 18 views
5

Mam poniższy kod do konwersji 32-bitowej wartości BCD (dostarczanej w dwóch uintach) do binarnej wartości uint.Najbardziej efektywny sposób konwersji BCD na binarny

Podane wartości mogą mieć wartość do 0x9999, tworząc maksymalną wartość 0x99999999.

Czy istnieje lepszy (tj. Szybszy) sposób, aby to osiągnąć?

/// <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

Wygląda cholernie dobry dla mnie. – Spence

+1

Dlaczego wymaga to dwóch uintów zamiast ushorts, jeśli każdy reprezentuje tylko 16 bitów? –

Odpowiedz

2

Twój kod wydaje się dość skomplikowany; Czy potrzebujesz konkretnego sprawdzania błędów?

W przeciwnym razie, można po prostu użyć następującego kodu, który nie powinien być dłuższy, w rzeczywistości, to w większości takie same:

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

Przypuszczam, że można rozwinąć pętlę:

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; 

Możesz sprawdzić następujące cyfry BCD:

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

To ustawienie jest nieprawidłowe dla niezerowej wartości e jeśli dowolna pojedyncza cyfra szesnastkowa> 9.

+0

To nie działa. Po rozwinięciu pętli należy pamiętać o "wartości >> = 4;" – epotter

6

Jeśli rozwiniesz pętlę, pamiętaj, aby zachować przesunięcie bitowe.

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

To powinno być połączone z odpowiedzią AShelly'ego – epotter

+0

Proszę wstawić parens wokół operatorów przekręcających bity - pierwszeństwo operatorów dla nich jest bardzo mylące dla większości ludzi. –

+0

Dobre połączenie. To sprawia, że ​​jest bardziej czytelny. – epotter

8

Jeśli masz dużo wolnego miejsca na tablicę elementów 39322, zawsze możesz po prostu sprawdzić wartość.

+0

Dla nieprzetworzonej prędkości stół z pewnością wygra. – ScottS

+0

Najszybsze rozwiązanie do tej pory. (poprosił o to) – GvS

0

Oczywiście istnieje bardziej wydajna metoda. to tylko przykład oczywiście, dzięki czemu można ustawić go jako lekcji ^^

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

Spróbuj tego:

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); 
} 
Powiązane problemy