我有一个32位定时器,我希望在n步之后溢出。这意味着每个步骤应为(2 ^ 32)/ n。但是,如果我尝试使用32位整数计算此数字,则编译器会抱怨(1 <&lt; 32)大于我正在使用的类型。
我可以非常接近我正在寻找的答案,而不是像(~0)/ n那样。然而,在这种情况下,当n为2的幂时,我不会得到正确的答案,这意味着在这些情况下,定时器溢出需要一个额外的步骤。
是否有一个简单的表达式只使用32位整数来计算(2 ^ 32)/ n?
答案 0 :(得分:4)
如果您希望计数器在第n步(当可能的话)时溢出,那么您需要计算ceil(232 / n)
。考虑两种可能的情况:
n不是2的幂。在这种情况下,n不是232
的因子,并且除法的上限恰好是地板的一个。此外,(使用截断整数除法,如在C或Java中)floor(232 / n) == floor((232 - 1) / n)
。所以步骤是(232 - 1)/n + 1
。
n是2的幂。在这种情况下,n精确地划分232
,因此(232 - 1) / n
将比232 / n
小一。所以步骤是(232 - 1)/n + 1
。方便的是,这与第一种情况下的值相同。
注意:正如@greybeard在评论中指出的那样,如果n > 216
,则无法保证存在适当的步长。对于较大的n
,上述过程将计算最大步长,以确保在步骤n
之前不会发生溢出。
答案 1 :(得分:1)
如果您使用C作为编程语言,则可以使用其无符号算术。请考虑以下事项:
floor(232 / n) = floor((232 - n) / n + 1)
如果您的n
具有无符号类型(例如uint32_t
),则数学表达式232 - n
可以简单地计算为-n
。
所以在C:
uint32_t n = ...;
uint32_t d = (-n) / n + 1;
可替换地:
uint32_t d = (0 - n) / n + 1;
你应该记录好,因为这是非常模糊的代码。