我有一个特殊的问题,我正在寻找一个有效的解决方案。我有一个字节数组,其中包含无符号4字节整数的最重要的n个字节(大多数sig字节优先)。剩余字节的值(如果有)是未知的。我需要检查部分已知的整数值是否落在已知整数的某个范围(+或 - x)内。它对于被测试的字节数组所表示的整数也有效。
我有一个有效的解决方案(如下)。问题是这个解决方案比我认为必要的方式执行更多的比较,并且在最小sig字节未知的情况下将重复整个比较负载。我很确定它可以更有效地完成,但无法弄清楚如何。最不重要的字节未知的情况是一个边缘情况,所以我可能能够使用它,但它构成了需要具有低延迟的系统的一部分,所以如果任何人都可以帮助解决这个问题,那将是很好的。
提前致谢。
static final int BYTES_IN_INT = 4;
static final int BYTE_SHIFT = 010;
// partial integer byte array length guaranteed to be 1-4 so no checking necessary
static boolean checkPartialIntegerInRange(byte[] partialIntegerBytes, int expectedValue, int range)
{
boolean inRange = false;
if(partialIntegerBytes.length == BYTES_IN_INT)
{
// normal scenario, all bytes known
inRange = Math.abs(ByteBuffer.wrap(partialIntegerBytes).getInt() - expectedValue) <= range;
}
else
{
// we don't know least significant bytes, could have any value
// need to check if partially known int could lie in the range
int partialInteger = 0;
int mask = 0;
// build partial int and mask
for (int i = 0; i < partialIntegerBytes.length; i++)
{
int shift = ((BYTES_IN_INT - 1) - i) * BYTE_SHIFT;
// shift bytes to correct position
partialInteger |= (partialIntegerBytes[i] << shift);
// build up mask to mask off expected value for comparison
mask |= (0xFF << shift);
}
// check partial int falls in range
for (int i = -(range); i <= range; i++)
{
if (partialInteger == ((expectedValue + i) & mask))
{
inRange = true;
break;
}
}
}
return inRange;
}
编辑:感谢下面的贡献者。这是我的新解决方案。欢迎评论。
static final int BYTES_IN_INT = 4;
static final int BYTE_SHIFT = 010;
static final int UBYTE_MASK = 0xFF;
static final long UINT_MASK = 0xFFFFFFFFl;
public static boolean checkPartialIntegerInRange(byte[] partialIntegerBytes, int expectedValue, int range)
{
boolean inRange;
if(partialIntegerBytes.length == BYTES_IN_INT)
{
inRange = Math.abs(ByteBuffer.wrap(partialIntegerBytes).getInt() - expectedValue) <= range;
}
else
{
int partialIntegerMin = 0;
int partialIntegerMax = 0;
for(int i=0; i < BYTES_IN_INT; i++)
{
int shift = ((BYTES_IN_INT - 1) - i) * BYTE_SHIFT;
if(i < partialIntegerBytes.length)
{
partialIntegerMin |= (((partialIntegerBytes[i] & UBYTE_MASK) << shift));
partialIntegerMax = partialIntegerMin;
}
else
{
partialIntegerMax |=(UBYTE_MASK << shift);
}
}
long partialMinUnsigned = partialIntegerMin & UINT_MASK;
long partialMaxUnsigned = partialIntegerMax & UINT_MASK;
long rangeMinUnsigned = (expectedValue - range) & UINT_MASK;
long rangeMaxUnsigned = (expectedValue + range) & UINT_MASK;
if(rangeMinUnsigned <= rangeMaxUnsigned)
{
inRange = partialMinUnsigned <= rangeMaxUnsigned && partialMaxUnsigned >= rangeMinUnsigned;
}
else
{
inRange = partialMinUnsigned <= rangeMaxUnsigned || partialMaxUnsigned >= rangeMinUnsigned;
}
}
return inRange;
}
答案 0 :(得分:1)
将无符号字节转换为整数。右移32-n(所以你有意义的字节是最小字节)。右移你的最小/最大整数相同的数量。如果您的移位测试值等于移位整数,则可能在该范围内。如果在它们之间,它肯定在范围内。
假设整数上的符号位始终为零(如果不是,则强制将负数转换为零,因为您的测试值不能为负)。但是因为那只有一位,除非你把全部32位作为n,否则这不重要(在这种特殊情况下它不是什么大问题)。
答案 1 :(得分:1)
假设您有一个顺时针间隔(x,y)和一个正常间隔(低,高)(每个包括它们的端点),确定它们是否相交可以完成(未测试):
if (x <= y) {
// (x, y) is a normal interval, use normal interval intersect
return low <= y && high >= x;
}
else {
// (x, y) wraps
return low <= y || high >= x;
}
要比较为无符号整数,您可以使用long
s(使用x & 0xffffffffL
进行反对来抵消符号扩展)或Integer.compareUnsigned
(在较新版本的Java中),或者如果您使用您更喜欢使用Integer.MIN_VALUE
添加/减去/ xor两个操作数。