我需要一个允许溢出的couter的代码,其中< >对于某些定义的时间间隔,继续告诉以后值的早期值。
澄清一下,一种可能的实施方式是:
考虑两个这样的计数器cur
和dut
(被测设备),考虑两个函数:
bool isEarlier(cur, dut) // Is dut earlier than cur?
bool isLater(cur, dut)
cur
和dut
是16位,cur
刚刚溢出,其当前值是,假设5
。根据{{1}}的值,函数将返回
dut
,isLater - &gt; (cur < dut)
我可以自己编写代码,没问题。我只是懒惰。我知道事实上在PostgreSQL中存在类似的东西(事务ids包装),我无法找到实际执行它的函数。我很确定在Linux内核中有类似的东西,可能是宏。但是更高级的谷歌代码搜索,以及/ usr / include / linux上的grep可能会把它变成现实。有什么想法吗?
澄清了cur和dut的作用。 “无效”是一种保障措施。随着cur和dut之间的差异变大,这个功能最终会引起注意。
答案 0 :(得分:3)
我认为你正在谈论正确处理数字圆的环绕。实际上这很容易。
这并不是你所说的(不确定为什么你有“异常”间隔),但是:
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)因为环绕计数器可以被解释为具有多个解mod6536,所以它选择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)将为false。
您有特定的间隔选择,这与我使用环绕数字的理由不同。这里定义的功能不能满足你所说的需求,但我觉得这些间隔的选择有点奇怪。也许你可以解释一下你是如何决定的?
答案 1 :(得分:1)
首先计算差异,然后检查它落入哪个窗口。
由于它非常简单并且过去/未来/错误窗口的大小各不相同,因此您必须自己完成。
答案 2 :(得分:1)
好的,记录。这是我的解决方案,这就是我的意思:
#include <stdint.h>
void increase_cyclic_counter (uint16_t *cnt)
{
#ifdef CYCLIC_COUNTER_EXPLICIT_WRAP
if (*cnt < 2^16-1)
*cnt++;
else
*cnt = 0;
#else
*cnt++;
#endif
}
#define SAME 1
#define LATER 0
#define EARLIER 2
#define FORBIDDEN -1
/* dut (device under test) is tested against cur
* returns:
* EARLIER (LATER) if dut happened earlier (later) in the sequence than cur
* SAME if dut == cur
* FORBIDDEN if dut and cur are that far away in the cyclic sequence
* that no unambigious jugement is possible
*
* The basic idea is the same as with two-character year codes, where
* '97' stands for 1997 and '11' stands for 2011. '50' is regarded as
* too ambigous and therefore rejected.
*
* The implementation splits the short integer range 0-65535 into 4 parts:
* 0-16383, 16384-32767, 32768-49151, 49152-65536
* With cur and dut in the same range, normal arithmetics apply, else the
* ranges are compared to each other.
*/
int test_cyclic_counter (uint16_t cur, uint16_t dut)
{
switch (((int)(cur>>14)) - ((int)(dut>>14)))
{
case 0: // same range
if (dut < cur)
return EARLIER;
else if (dut == cur)
return SAME;
else
return LATER;
case 1:
case -3:
return EARLIER;
case 3:
case -1:
return LATER;
default:
return FORBIDDEN;
}
}
答案 3 :(得分:0)
在我看来你刚刚写了:)。 为什么不将你的帖子翻译成一些C代码?
答案 4 :(得分:0)
请记住,你不能得到“&gt;”和“&lt;”在C中做你想做的事。它们仅适用于数字,并且没有运算符重载。同样的事情也适用于你的例外; C没有例外。
你可以编写一些访问函数,以这种方式处理无符号整数类型,这并不困难。 (在C中,对于有符号整数类型,溢出是未定义的,尽管在大多数现代系统中它都包含在内。)这不会那么困难。