2009-01-20 7 views
5

J'ai le code ci-dessous pour convertir une valeur BCD de 32 bits (fournie en deux moitiés uint) en une valeur binaire uint.Le moyen le plus efficace de convertir BCD en binaire

Les valeurs fournies peuvent être jusqu'à 0x9999, pour former une valeur maximale de 0x99999999.

Existe-t-il une meilleure façon (c'est-à-dire plus rapide) d'y parvenir?

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

semble assez sacrément bon pour moi. – Spence

+1

Pourquoi faut-il deux uints plutôt que des ushorts, si chacun ne représente que 16 bits? –

Répondre

2

Votre code semble plutôt compliqué; Avez-vous besoin de la vérification d'erreur spécifique?

Sinon, vous pouvez simplement utiliser le code suivant qui ne devrait pas être plus lent, en fait, il est surtout le même:

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

Je suppose que vous pouvez déroulez la boucle:

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; 

Et vous pouvez vérifier les chiffres BCD invalides comme ceci:

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

Valeurs non valides pour une valeur non nulle e si un chiffre hexadécimal unique> 9.

+0

Cela ne fonctionne pas tout à fait. Lorsque vous déroulerez la boucle, vous devez vous souvenir de la "valeur >> = 4;" – epotter

6

Si vous déroulez la boucle, souvenez-vous de garder le décalage de bits.

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

Ceci devrait être combiné avec la réponse d'AShelly – epotter

+0

Veuillez mettre les parens autour des opérateurs de twiddling de bit - la priorité d'opérateur pour eux est très confuse pour la plupart des personnes. –

+0

Bon appel. Cela le rend beaucoup plus lisible. – epotter

8

Si vous avez l'espace d'épargner pour un ensemble d'éléments 39322, vous pouvez toujours regarder la valeur juste vers le haut.

+0

Pour la vitesse brute, une table de consultation va certainement gagner. – ScottS

+0

La solution la plus rapide jusqu'à présent. (Il l'a demandé) – GvS

0

Bien sûr, il existe une méthode plus efficace. c'est juste un exemple bien sûr, vous pouvez régler comme une leçon ^^

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

Essayez ceci:

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); 
} 
Questions connexes