Java 检查部分已知整数是否在某个范围内
我有一个特殊的问题,我正在寻找一个有效的解决办法。我有一个字节数组,它包含无符号4字节整数中最重要的n个字节(首先是最重要的sig字节)。剩余字节(如果有)的值未知。我需要检查部分已知的整数值是否在已知整数的特定范围(+或-x)内。对于被测试字节数组表示的整数,它也是有效的 我有一个有效的解决方案(见下文)。问题是,这个解决方案执行的比较比我认为必要的多,并且在最小sig字节未知的场景中,整个比较负载将被复制。我很确定这可以做得更有效,但不知道如何做。最低有效字节未知的场景是一个边缘情况,因此我可以接受它,但它构成了一个系统的一部分,需要低延迟,因此如果有人能够提供帮助,那将是非常好的 提前谢谢Java 检查部分已知整数是否在某个范围内,java,performance,int,bit-manipulation,low-level,Java,Performance,Int,Bit Manipulation,Low Level,我有一个特殊的问题,我正在寻找一个有效的解决办法。我有一个字节数组,它包含无符号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;
静态最终整数字节_移位=010;
//部分整数字节数组长度保证为1-4,因此无需检查
静态布尔检查PartialIntegerRange(字节[]partialIntegerBytes,int expectedValue,int range)
{
布尔inRange=false;
if(partialIntegerBytes.length==BYTES\u IN\u INT)
{
//正常情况下,所有字节都已知
inRange=Math.abs(ByteBuffer.wrap(partialIntegerBytes).getInt()-expectedValue)将无符号字节转换为整数。右移32-n(因此有意义的字节为最小字节)。将最小/最大整数右移相同的量。如果移位测试值等于其中一个移位整数,则可能在范围内。如果介于两者之间,则肯定在范围内
假设整数上的符号位始终为零(如果不是,则强制将负数转换为零,因为测试值不能为负数)。但因为这只是一位,除非将所有32位都指定为n,否则这不重要(在这种特殊情况下,这不是什么大问题)。假设有一个顺时针间隔(x,y)和一个正常间隔(低,高)(每个包括其端点),确定它们是否可以相交(未测试):
if(x)有两个范围;int的可能值范围和“允许的”范围。每个范围由两个端点定义。你所要做的就是确定。你不能用0x00
和0xff
填充未知字节,并使用这两个可能的数字作为它可能变成的数字的最小/最大值吗?只要检查这两个数字都在你的范围内,你就完成了。我想我需要使用一个组合这两个答案中有n个。@OldCurmudgeon,我想知道未知数是否可能,不确定是否在范围内。未知数的最小和最大可能值可能都在范围外,但它仍然可能有一个在范围内的值,在这种情况下,我希望我的方法返回true。我将根据您的建议使用最小值和最大值来确定是否存在与其他建议相同的范围交集。谢谢你们。现在要解决的问题是如何处理整型环绕和java中的无符号值…@paddy with wrapparound,这些间隔称为“顺时针间隔”,你仍然可以将它们相交。只是有点棘手。我会找到它,然后再给你回复。这看起来像是我想要的。O(1)时间复杂性。谢谢。
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;
}
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;
}