5

BCDを使用してintをbyte[2]配列に変換したいと思います。

問題のintは、年を表すDateTimeから取得され、2バイトに変換する必要があります。

これを行う既成の関数はありますか、それともこれを行う簡単な方法を教えていただけますか?

例:

int year = 2010

出力します:

byte[2]{0x20, 0x10};
4

9 に答える 9

11
    static byte[] Year2Bcd(int year) {
        if (year < 0 || year > 9999) throw new ArgumentException();
        int bcd = 0;
        for (int digit = 0; digit < 4; ++digit) {
            int nibble = year % 10;
            bcd |= nibble << (digit * 4);
            year /= 10;
        }
        return new byte[] { (byte)((bcd >> 8) & 0xff), (byte)(bcd & 0xff) };
    }

ビッグエンディアンの結果を要求したことに注意してください。これは少し珍しいことです。

于 2010-03-15T16:02:19.487 に答える
8

この方法を使用してください。

    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より大きい場合、値は4バイトに収まりません。より正式には、値が0未満または10 ^(n * 2)以上の場合(nはバイト数)、値はnバイトに収まりません。
  • バイトごとに:
    • そのバイトを、バイトの10で割った値の余りに設定します。(これにより、最後の桁が現在のバイトの下位ニブル[ハーフバイト]に配置されます。)
    • 値を10で割ります。
    • 10で割った値の余りの16倍をバイトに追加します。(これにより、現在のバイトの上位ニブルに最後の桁が配置されます。)
    • 値を10で割ります。

(1つの最適化は、すべてのバイトを事前に0に設定することです(これは、新しい配列を割り当てるときに.NETによって暗黙的に行われます)。値が0に達すると、反復を停止します。この後者の最適化は、上記のコードでは実行されません。また、利用可能な場合、一部のコンパイラまたはアセンブラは、1つの除算ステップで商と剰余を取得できる除算/剰余ルーチンを提供しますが、最適化は通常は必要ありません。)

于 2011-08-18T12:33:35.433 に答える
3

これはひどいブルートフォースバージョンです。これよりも良い方法があると確信していますが、とにかくうまくいくはずです。

int digitOne = year / 1000;
int digitTwo = (year - digitOne * 1000) / 100;
int digitThree = (year - digitOne * 1000 - digitTwo * 100) / 10;
int digitFour = year - digitOne * 1000 - digitTwo * 100 - digitThree * 10;

byte[] bcdYear = new byte[] { digitOne << 4 | digitTwo, digitThree << 4 | digitFour };

それについての悲しい部分は、高速のバイナリからBCDへの変換がx86マイクロプロセッサアーキテクチャに組み込まれていることです。

于 2010-03-15T15:52:18.293 に答える
3

これは、ジェフリーのバージョンよりも少しクリーンなバージョンです。

static byte[] IntToBCD(int input)
{
    if (input > 9999 || input < 0)
        throw new ArgumentOutOfRangeException("input");

    int thousands = input / 1000;
    int hundreds = (input -= thousands * 1000) / 100;
    int tens = (input -= hundreds * 100) / 10;
    int ones = (input -= tens * 10);

    byte[] bcd = new byte[] {
        (byte)(thousands << 4 | hundreds),
        (byte)(tens << 4 | ones)
    };

    return bcd;
}
于 2010-03-15T15:58:22.977 に答える
2

多分このループを含む単純な解析関数

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++;
}
于 2011-08-18T12:16:35.363 に答える
1

より一般的な解決策

    private IEnumerable<Byte> GetBytes(Decimal value)
    {
        Byte currentByte = 0;
        Boolean odd = true;
        while (value > 0)
        {
            if (odd)
                currentByte = 0;

            Decimal rest = value % 10;
            value = (value-rest)/10;

            currentByte |= (Byte)(odd ? (Byte)rest : (Byte)((Byte)rest << 4));

            if(!odd)
                yield return currentByte;

            odd = !odd;
        }
        if(!odd)
            yield return currentByte;
    }
于 2012-02-22T13:30:05.177 に答える
1

Peter O.と同じバージョンですが、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メソッドを使用します。

于 2016-09-02T07:09:32.093 に答える
0

IntToByteArrayに投稿された、次のように使用できる汎用ルーチンを作成しました。

var yearInBytes = ConvertBigIntToBcd(2010、2);

于 2013-01-04T16:01:34.867 に答える
-3
static byte[] IntToBCD(int input) { 
    byte[] bcd = new byte[] { 
        (byte)(input>> 8), 
        (byte)(input& 0x00FF) 
    };
    return bcd;
}
于 2011-08-11T01:58:53.420 に答える