1

I am writing a FIX/FAST decoder for negative numbers as described below:

enter image description here

My question is:

How to fill the high-end bits of a Java byte with 1s as it is described above? I am probably unaware of some bit manipulation magic I need to in this conversion.

So I need to go from 01000110 00111010 01011101 to 11110001 10011101 01011101.

I know how to shift by 7 to drop the 8th bit. What I don't know is how to fill the high-end bits with 1s.

4

5 回答 5

2

您提出的问题似乎与您要解决的问题并不相符。1你不是想用;填充高位。您正在尝试从缓冲区解码停止位编码的整数,这涉及在组合有效负载位时丢弃符号位。而且,当然,您希望在找到一个1在停止位位置带有 a 的字节后停止。以下方法应正确解码该值:

private static final byte SIGN_BIT = (byte)0x40;
private static final byte STOP_BIT = (byte)0x80;
private static final byte PAYLOAD_MASK = 0x7F;

public static int decodeInt(final ByteBuffer buffer) {
    int value = 0;
    int currentByte = buffer.get();

    if ((currentByte & SIGN_BIT) > 0)
        value = -1;

    value = (value << 7) | (currentByte & PAYLOAD_MASK);
    if ((currentByte & STOP_BIT) != 0)
        return value;

    currentByte = buffer.get();
    value = (value << 7) | (currentByte & PAYLOAD_MASK);
    if ((currentByte & STOP_BIT) != 0)
        return value;

    currentByte = buffer.get();
    value = (value << 7) | (currentByte & PAYLOAD_MASK);
    if ((currentByte & STOP_BIT) != 0)
        return value;

    currentByte = buffer.get();
    value = (value << 7) | (currentByte & PAYLOAD_MASK);
    if ((currentByte & STOP_BIT) != 0)
        return value;

    currentByte = buffer.get();
    value = (value << 7) | (currentByte & PAYLOAD_MASK);
    return value;
}

循环会更干净,但我手动展开它,因为消息传递协议往往是热代码路径,并且有一个固定的最大字节长度(5 个字节)。为简单起见,我从 a 读取字节ByteBuffer,因此您可能需要根据读取编码数据的方式调整逻辑。

于 2014-09-05T18:09:16.017 回答
1

填充高位可能如下:

int fillHighBits(int b) {             // 0001abcd
    int n = Integer.highestOneBit(b); // 00010000
    n = ~n;                           // 11101111
    ++n;                              // 11110000
    return (n | b) 0xFF;              // 1111abcd
}

作为表达式

(~Integer.highestOneBit(b) + 1) | b

尽管您提供的示例让我怀疑这是否是您想要的。

于 2014-09-05T16:01:23.083 回答
1

这可以非常简单地使用一个简单的累加器来完成,一次移入 7 位。您需要跟踪累加器中有多少位。

符号扩展可以通过简单的逻辑左移然后算术右移(相同距离)来执行,以将最高位复制到所有未使用的位置。

byte[] input = new byte[] { 0x46, 0x3A, (byte) 0xDD };
int accumulator = 0;
int bitCount = 0;
for (byte b : input) {
    accumulator = (accumulator << 7) | (b & 0x7F);
    bitCount += 7;
}
// now sign extend the bits in accumulator
accumulator <<= (32 - bitCount);
accumulator >>= (32 - bitCount);
System.out.println(Integer.toHexString(accumulator));

整个技巧是 >>N 运算符复制最高位 N 次。

于 2014-09-05T17:04:23.230 回答
0

像这样的东西:

int x = ...; x = x | 0xF000;

于 2014-09-05T15:09:39.640 回答
0

用高位设置为 1 且其余为 0 的数字执行逻辑OR( )|

例如:

   1010101010101010
OR 1111111100000000
--------------------
   11111111101010101
于 2014-09-05T15:07:41.860 回答