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 half提供)转换为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;
}
7 个解决方案
#1
If you've space to spare for a 39,322 element array, you could always just look the value up.
如果你有足够的空间来容纳39,322元素阵列,你可以随时查看值。
#2
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;
#3
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;
#4
Try this:
public static int bcd2int(int bcd) {
return int.Parse(bcd.ToString("X"));
}
#5
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,则将无效值设置为非零值。
#6
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;
}
#7
public static uint BCDToNum(int num)
{
return uint.Parse(num.ToString(), System.Globalization.NumberStyles.HexNumber);
}
#1
If you've space to spare for a 39,322 element array, you could always just look the value up.
如果你有足够的空间来容纳39,322元素阵列,你可以随时查看值。
#2
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;
#3
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;
#4
Try this:
public static int bcd2int(int bcd) {
return int.Parse(bcd.ToString("X"));
}
#5
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,则将无效值设置为非零值。
#6
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;
}
#7
public static uint BCDToNum(int num)
{
return uint.Parse(num.ToString(), System.Globalization.NumberStyles.HexNumber);
}