5

CashRegister Machine によって作成された Hex ファイルがあります。このファイルを読み込む必要があります。

ファイルは、以下に詳述するフォーマットを使用します。ソケットパケットのようなものです。

コード データ:2 バイト
PLU コード データ:7 バイト
単価データ:5 バイト
数量データ:5 バイト
合計金額データ:5 バイト
PLU 名データ:18 バイト
税率データ:1 バイト
長さ:24 + 19 バイト

  • PLUコード形式はBCD
  • 単価 1~9999999999(BCD)
  • 数量 1 ~ 9999999999 (BCD の最後の 3 つの数字は 10 進数である必要があります)
  • 合計金額 1~9999999999(BCD)

バイナリ リーダーで 16 進ファイルを読み込んでから、単価のバイト配列を挿入します。

byte[] bytes = { data[21], data[22], data[23], data[24], data[25] }; // BCD Byte Array

この配列は単価です。しかし、どうすればこの数値を 10 進数に変換できますか。そして、情報によると、数量: BCD の最後の数値は 10 進数である必要があります。これはどういう意味ですか? ありがとう。

4

5 に答える 5

10

BCD番号は、0〜9の値を4ビットにエンコードします。パックされたBCD(おそらくあなたが扱っているもの)では、バイトは、バイトの各ニブル(4ビット)に1つずつ、0から9までの2つの値を含むために使用されます。intに変換するには、少しいじる必要があります。たとえば、次の例では、BCDバイトの配列を最大9桁を保持できるintに変換します。9 bcd桁を超える入力がある場合は、longを使用します。

// assume byte[] bcds is input
int result = 0;
foreach(byte bcd in bcds) {
    result *= 100;
    result += (10 * (bcd >> 4));
    result += bcd & 0xf;
}

これは、各バイトがビッグエンディアンBCDとして格納されていることを前提としています。ここで、最上位桁はバイトの最上位ニブルにあります。これは、より一般的な実装としてBCDのウィキペディアページで説明されているものです。リトルエンディアンのBCDを扱っている場合、forループ内の変換コードは次のようになります。

    result *= 100;
    result += (10 * (bcd & 0xf));
    result += bcd >> 4;

また、配列のエンディアンが正しいことを確認する必要があります。つまり、配列の最初のバイトに最上位2桁、または最下位2桁が含まれていることを確認する必要があります。たとえば、123456という数値はパックされたBCDを使用すると3バイトに収まります。12はbyte[0]またはbyte[2]ですか?エンディアンが私の想定と異なる場合は、上記のループを調整して順序を逆にする必要があります。12はbyte[0](ビッグエンディアン、最下位桁が左端のバイト)にあると想定しています。

BCDと小数で表される数量については、実際の値を見て、彼らが何を話しているのかを理解する必要があります。

于 2012-07-28T13:03:19.537 に答える
5

各バイトは、各ニブルに 1 つずつ、2 つの 10 進数です。バイトを 16 進数で表示すると、数字を簡単に読み取ることができます。

0x08 0x27 0x42 0x17 0x75 = 827,421,775

次のように高ニブルと低ニブルを取得できます。

int high = currentByte >> 4;
int low = currentByte & 0xF;

次のように、各バイトを数値に変換します。

int number = 10 * high + low;

ただし、各バイトは次のバイトよりも 100 倍大きいことに注意してください。

数量が小数点以下 3 桁の場合、最終的な数値を 1,000 で割るだけで実際の値が得られます。

于 2012-07-28T13:20:20.667 に答える
0

私の回答は質問に対して少し遅れているかもしれませんが、質問を解決した方法は次のとおりです。

1- まず、数字の長さを見つける必要がありました。例: 3422 -> 4、100 -> 3

public static class NumbersUtility
{
    public static int FindNumberLength(int number)
    {
        return Convert.ToInt32( Math.Floor(Math.Log(number,10))+1);
    }

    public static int FindNumberDivisor(int number)
    {
        return Convert.ToInt32(Math.Pow(10, FindNumberLength(number)-1));
    }

    public static int[] FindNumberElements(int number)
    {
        int[] elements = new int[FindNumberLength(number)];
        int divisor = FindNumberDivisor(number);
        for (int i = 0; i < elements.Length; i++)
        {
            elements[i] = number/divisor;
            number %= divisor;
            divisor /= 10;
        }
        return elements;
    }
}

その後、数値を配列に分割して、数値のトラバースと処理を容易にしました。ただし、1 つの注意点があります。数値の長さが奇数の場合、配列の先頭にゼロを追加する必要があります。

       public static byte[] IntToBCD(int[] input, bool isLittleEndian = false)
    {
        byte[] outArr = new byte[Convert.ToInt32(Math.Ceiling((double) input.Length/2))];

        //Handle the case of an odd number in which a zero should be added at the beginning
        if (input.Length%2 != 0)
        {
            //Use a temp array to expand the old one, you can use lists or 
            //anyother datastructure if you wish to
            int[] newInput = new int[input.Length+1];
            Array.Copy(input,0,newInput,1,input.Length);
            newInput[0] = 0;
            input = newInput;
            //Dispose the temp array
            newInput = null;
        }

        for (int i = 0; i < outArr.Length; i++)
        {

            outArr[i]=(byte)(input[i*2]<<4);
            outArr[i]|=(byte)(input[i*2+1]);
        }
        return outArr;
    }
于 2016-02-09T10:53:29.580 に答える