我认为您正在谈论正确处理数字圈的环绕。实际上,这很容易。
这并没有完全按照您所说的进行(不确定为什么您有那个“异常”间隔),但是:
typedef unsigned short uint16_t;
typedef signed short int16_t;
// abstract out 16-bit types in case "short" doesn't correspond to 16bits
bool isEarlier(uint16_t a, uint16_t b)
{
int16_t diff = a-b;
return diff < 0;
}
bool isLater(uint16_t a, uint16_t b)
{
int16_t diff = a-b;
return diff > 0;
}
编辑:这在 diff=-32768 处有一个“分支点”,因此如果 a=5 和 b=32772,则 diff=-32767 小于 0,因此 5 比 32772“早”。如果 a=5 和b=32774, diff=-32769=32767 大于 0,因此 5 比 32774“晚”。这定义了(a)最简单的数学意义上的“早”和“晚”,以及(b)因为环绕计数器可以解释为具有多个解决方案 mod 65536,它选择相对于数字圈彼此“最接近”的 a 和 b 的解决方案。
如果 a 和 b 相差 32768,那么它们之间的距离相等,并且使用简单的数学来选择最简单的方法……这“违反”了“较早”和“较晚”的反对称性质,即 isLater(5,32773)是真的,isLater(32773,5) 也是真的。但是你怎么知道是“5”表示计数为5,还是“5”表示计数为65541?(就像 abs(-32768) == -32768 给出了一个奇怪的荒谬答案)如果你想保持反对称,例如 isLater(b,a) == isEarlier(a,b),那么你总是可以这样做:
bool isLater(uint16_t a, uint16_t b)
{
int16_t diff = b-a;
return diff < 0;
}
如果您希望将分支点偏向一个方向以在 -32768+K 处发生,请改用它:
bool isEarlier(uint16_t a, uint16_t b)
{
int16_t diff = a-b-K;
return diff < -K;
}
bool isLater(uint16_t a, uint16_t b)
{
int16_t diff = b-a-K;
return diff < -K;
}
这不再使用最接近的;例如,如果 K=12768 和 a=5,那么对于 b=6,7,8,9,... 20005,isEarlier(a,b) 和 isLater(b,a) 将为真,并且对于b=20006, 20007, ... 65534, 65535, 0, 1, 2, 3, 4, 5 isEarlier(a,b) 和 isLater(b,a) 将为假。
您可以选择特定的间隔,这与我使用环绕数字的基本原理不同。这里定义的函数不能满足你所说的需求,但我发现这些间隔的选择有点奇怪。也许您可以解释一下您是如何确定它们的?