Преобразование Int в байтовый массив BCD - PullRequest
5 голосов
/ 18 августа 2011

Я хочу преобразовать int в массив байтов [4], используя BCD.

Указанный int будет получен из идентификатора устройства и необходимого ему устройства для связи с устройством через последовательный порт.

Есть ли какая-нибудь готовая функция, которая делает это, или вы можете дать мне простой способ сделать это?

пример:

int id= 29068082

будет выводить:

byte[4]{0x82, 0x80, 0x06, 0x29};

Ответы [ 3 ]

7 голосов
/ 18 августа 2011

Используйте этот метод.

    public static byte[] ToBcd(int value){
        if(value<0 || value>99999999)
            throw new ArgumentOutOfRangeException("value");
        byte[] ret=new byte[4];
        for(int i=0;i<4;i++){
            ret[i]=(byte)(value%10);
            value/=10;
            ret[i]|=(byte)((value%10)<<4);
            value/=10;
        }
        return ret;
    }

По сути, так оно и есть.

  • Если значение меньше 0 или больше 99999999, значение не помещается в четыре байта.Более формально, если значение меньше 0 или равно 10 ^ (n * 2) или больше, где n - количество байтов, значение не уместится в n байтов.
  • Для каждого байта:
    • Установите этот байт на остаток от значения, деленного на 10, до байта.(Это поместит последнюю цифру в младший полубайт [полубайта] текущего байта.)
    • Разделите значение на 10.
    • Добавьте 16 раз остаток от значения, разделенного на значение-10 к байту.(Это поместит последнюю последнюю цифру в верхний бит текущего байта.)
    • Разделите значение на 10.

(Одна оптимизацияустановить каждый байт в 0 заранее - что неявно делается .NET, когда он выделяет новый массив - и прекратить итерации, когда значение достигает 0. Эта последняя оптимизация не выполняется в приведенном выше коде для простоты.если возможно, некоторые компиляторы или ассемблеры предлагают процедуру деления / остатка, которая позволяет получить частное и остаток за один шаг деления, хотя оптимизация обычно не требуется.)

1 голос
/ 02 сентября 2016

Та же версия, что и у Питера О., но в VB.NET

Public Shared Function ToBcd(ByVal pValue As Integer) As Byte()
    If pValue < 0 OrElse pValue > 99999999 Then Throw New ArgumentOutOfRangeException("value")

    Dim ret As Byte() = New Byte(3) {} 'All bytes are init with 0's

    For i As Integer = 0 To 3
      ret(i) = CByte(pValue Mod 10)
      pValue = Math.Floor(pValue / 10.0)
      ret(i) = ret(i) Or CByte((pValue Mod 10) << 4)
      pValue = Math.Floor(pValue / 10.0)
      If pValue = 0 Then Exit For
    Next

    Return ret
End Function

Хитрость в том, чтобы понять, что простое использование pValue / = 10 округляет значение, поэтому, если, например, аргумент равен «16», первая часть байта будет правильной, но результат деления 2 (как 1.6 будет округлено). Поэтому я использую метод Math.Floor.

1 голос
/ 18 августа 2011

может быть простая функция разбора, содержащая этот цикл

i=0;
while (id>0)
{
    twodigits=id%100; //need 2 digits per byte
    arr[i]=twodigits%10 + twodigits/10*16;  //first digit on first 4 bits second digit shifted with 4 bits
    id/=100;

    i++;
}
...