C# 将 BCD 转换为二进制的最有效方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/462970/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 04:23:33  来源:igfitidea点击:

Most efficient way to convert BCD to binary

c#binarybcd

提问by Andy

I have the code below to convert a 32 bit BCD value (supplied in two uint halves) to a uint binary value.

我有下面的代码将 32 位 BCD 值(以两个 uint 一半提供)转换为 uint 二进制值。

The values supplied can be up to 0x9999, to form a maximum value of 0x99999999.

提供的值可以达到 0x9999,形成最大值 0x99999999。

Is there a better (ie. quicker) way to achieve this?

有没有更好(即更快)的方法来实现这一目标?

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

回答by Konrad Rudolph

Your code seems rather complicated; do you require the specific error checking?

你的代码看起来相当复杂;你需要特定的错误检查吗?

Otherwise, you could just use the following code which shouldn't be slower, in fact, it's mostly the 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;

回答by AShelly

I suppose you could unroll the loop:

我想你可以展开循环:

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;

And you can check for invalid BCD digits like this:

您可以像这样检查无效的 BCD 数字:

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

This sets invalid to a non-zero value if any single hex digit > 9.

如果任何单个十六进制数字 > 9,则将无效设置为非零值。

回答by epotter

If you unroll the loop, remember to keep the bit shift.

如果您展开循环,请记住保持位移。

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;

回答by Pete Kirkham

If you've space to spare for a 39,322 element array, you could always just look the value up.

如果您有足够的空间容纳 39,322 个元素的数组,您可以随时查看该值。

回答by Pete Kirkham

Of course, there are a more efficient method. this is just a example of course, so you can tune it as a lesson ^^

当然,还有更有效的方法。这当然只是一个例子,因此您可以将其作为课程进行调整^^

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;    

}

}

回答by ToF

Try this:

尝试这个:

public static int bcd2int(int bcd) {
   return int.Parse(bcd.ToString("X"));
}

回答by Andrew Mikhailov

public static uint BCDToNum(int num)
{
    return uint.Parse(num.ToString(), System.Globalization.NumberStyles.HexNumber);
}