0

これが私のコードです:

    long x1 = -123;
    long y1 = -312;
    long x2 = -111;
    long y2 = -112;
    long packed = x1 | y1 << 15 | x2 << 30 | y2 << 45;
    Debug.log("x1:" + ((packed) & 0b111111111111111));
    Debug.log("y1:" + ((packed >> 15) & 0b111111111111111));
    Debug.log("x2:" + ((packed >> 30) & 0b111111111111111));
    Debug.log("y2:" + ((packed >> 45) & 0b111111111111111));

x1、x2、x3、x4 を最大 16384(2^14) にする必要があります。したがって、+- 記号を追加すると、合計 15 ビットになります。誤った値が取得されるのはなぜですか?

4

4 に答える 4

1

これを試して

long pack(long v, int shift) {
    return (v & 0b111111111111111) << (shift * 15);
}

long unpack(long v, int shift) {
    long r = v >> (shift * 15) & 0b111111111111111;
    if ((r & 0b100000000000000) != 0)
        r |= ~0b111111111111111;
    return r;
}

    long x1 = -123;
    long y1 = -312;
    long x2 = -111;
    long y2 = -112;
    long packed = pack(x1, 0) | pack(y1, 1) | pack(x2, 2) | pack(y2, 3);
    Debug.log("x1:" + unpack(packed, 0));
    Debug.log("y1:" + unpack(packed, 1));
    Debug.log("x2:" + unpack(packed, 2));
    Debug.log("y2:" + unpack(packed, 3));

一般化されたバージョン:

long pack(long v, int width, int shift) {
    long mask = -1 >>> Long.SIZE - width;
    return (v & mask) << (shift * width);
}

long unpack(long v, int width, int shift) {
    long mask = -1 >>> Long.SIZE - width;
    long r = v >> (shift * width) & mask;
    if ((r & (1 << width - 1)) != 0)
        r |= ~mask;
    return r;
}

widthこの場合、引数に 15 を指定します。

于 2016-01-15T21:31:04.877 に答える
1

値をまとめる前に、関心のあるビットをマスクする必要があります。long としての -111 のほとんどのビットは設定されており、パックしている他の値と一緒に or を取得しています。

ビットフィールドを使用する方が簡単な場合があり、コンパイラーにすべてのマスキングとシフトを処理させることができます。

struct packedCoords
{
    long long x1 : 15;
    long long y1 : 15;
    long long x2 : 15;
    long long y2 : 15;
};

packedCoords test;
test.x1 = -123;
test.y1 = -312;
test.x2 = -111;
test.y2 = -112;

printf("sizeof packedCoords = %d\n", sizeof(packedCoords));
printf("x1: %d\n", static_cast<int>(test.x1));
printf("y1: %d\n", static_cast<int>(test.y1));
printf("x2: %d\n", static_cast<int>(test.x2));
printf("y2: %d\n", static_cast<int>(test.y2));
于 2016-01-15T19:40:12.593 に答える
1

余分なセットビットが問題であり、マスクする必要があると(おそらくIronMensanの回答から)推測したようです。

前後のコメントの罰として、「マジック ナンバー」の使用を減らすために、いくつかのコードを書き、それを少し一般化しました。これは C# で書かれていますが、この目的では Java と非常によく似ています。

long x1 = -345;
long y1 = 299;
long x2 = -111;
long y2 = -112;

int bitLengthToPack = 15;

long signBit = 1 << (bitLengthToPack - 1);
long dataBits = (signBit << 1) - 1;
long upperBits = ~dataBits;

long packed = (x1 & dataBits) | (y1 & dataBits) << bitLengthToPack | (x2 & dataBits) << (bitLengthToPack * 2) | (y2 & dataBits) << (bitLengthToPack * 3);

long x1e = packed & dataBits;

if ((x1e & signBit) > 0)
{
    x1e = x1e | upperBits;
}

Console.WriteLine("x1e: " + x1e);

long y1e = (packed >> bitLengthToPack) & dataBits;
if ((y1e & signBit) > 0)
{
    y1e = y1e | upperBits;
}

Console.WriteLine("y1e: " + y1e);

long x2e = (packed >> (bitLengthToPack * 2)) & dataBits;
if ((x2e & signBit) > 0)
{
    x2e = x2e | upperBits;
}

Console.WriteLine("x2e: " + x2e);

long y2e = (packed >> (bitLengthToPack * 3)) & dataBits;
if ((y2e & signBit) > 0)
{
    y2e = y2e | upperBits;
}

Console.WriteLine("y2e: " + y2e);

値の範囲が狭い場合は、 の値を減らすことができますbitLengthToPack。アンパックから条件を削除する方法が思いつきませんでした。おそらく私よりも独創的な誰か。

于 2016-01-15T21:24:04.830 に答える