5

32 ビット BCD 値 (2 つの uint 半分で提供) を uint バイナリ値に変換するコードを以下に示します。

指定できる値は最大 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;
    }
4

7 に答える 7

8

39,322 要素の配列に余裕がある場合は、いつでも値を調べることができます。

于 2009-01-21T13:57:18.680 に答える
7

ループを展開する場合は、ビット シフトを維持することを忘れないでください。

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;
于 2009-01-21T02:33:41.197 に答える
3

あなたのコードはかなり複雑に見えます。特定のエラーチェックが必要ですか?

それ以外の場合は、遅くないはずの次のコードを使用できます。実際、ほとんど同じです。

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;
于 2009-01-20T20:41:42.203 に答える
1

これを試して:

public static int bcd2int(int bcd) {
   return int.Parse(bcd.ToString("X"));
}
于 2010-12-28T16:23:05.723 に答える
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

これは、単一の 16 進数が 9 より大きい場合、無効をゼロ以外の値に設定します。

于 2009-01-20T20:56:38.287 に答える
1
public static uint BCDToNum(int num)
{
    return uint.Parse(num.ToString(), System.Globalization.NumberStyles.HexNumber);
}
于 2011-09-25T07:28:53.363 に答える
-1

もちろん、もっと効率的な方法があります。これはもちろん一例ですので、レッスンとしてチューニングできます^^

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;    

}

于 2009-05-21T12:38:10.720 に答える