2009-01-20 16 views
5

Tengo el siguiente código para convertir un valor de BCD de 32 bits (suministrado en dos mitades de uint) a un valor binario uint.La manera más eficiente de convertir BCD a binario

Los valores suministrados pueden ser de hasta 0x9999, para formar un valor máximo de 0x99999999.

¿Existe alguna forma mejor (es decir, más rápida) de lograr esto?

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

Se ve bastante bien para mí. – Spence

+1

¿Por qué se necesitan dos uints en lugar de ushorts, si cada uno solo representa 16 bits? –

Respuesta

2

Su código parece bastante complicado; ¿necesita la verificación de errores específicos?

De lo contrario, usted podría utilizar el siguiente código que no debe ser más lento, de hecho, es prácticamente el mismo:

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

supongo que se podría desenrollar el bucle:

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; 

y se puede comprobar si hay dígitos BCD válidos como este:

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

ajusta no válida a un no-cero Valu e si hay un solo dígito hexadecimal> 9.

+0

Esto no funciona del todo. Cuando desenrollas el ciclo, debes recordar el "valor >> = 4;" – epotter

6

Si desenrolla el lazo, recuerde mantener la broca desplazada.

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

Esto se debe combinar con la respuesta de AShelly – epotter

+0

. Ponga los parens alrededor de los operadores que manipulan los bits: la precedencia del operador para ellos es muy confusa para la mayoría de las personas. –

+0

Buena llamada. Eso lo hace mucho más legible. – epotter

8

Si usted tiene espacio de sobra para una matriz de 39.322 elementos, siempre se puede simplemente mirar el valor hacia arriba.

+0

Para velocidad bruta, una tabla de búsqueda ciertamente va a ganar. – ScottS

+0

La solución más rápida hasta el momento. (lo pidió) – GvS

0

Por supuesto, hay un método más eficiente. Esto es sólo un ejemplo de por supuesto, para que pueda sintonizar como una lección ^^

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

Prueba esto:

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); 
} 
Cuestiones relacionadas