Reputation: 2315
I have a 32-bit timer which I want to overflow after n steps. This means each step should be (2^32)/n. However, if I try to compute this number using 32-bit integers, the compiler complains that (1<<32) is larger than the type I'm using.
I could come quite close to the answer I'm looking for by instead doing something like (~0)/n. However, it bugs me that in this case I would not get the correct answer when n is a power of 2, which means in those cases it would take one extra step for the timer to overflow.
Is there a simple expression to calculate (2^32)/n using only 32-bit integers?
Upvotes: 3
Views: 706
Reputation: 241861
If you want the counter to overflow on precisely the nth step (when this is possible), then you need to compute ceil(232 / n)
. Consider the two possible cases:
n is not a power of 2. In this case, n is not a factor of 232
, and the ceiling of the division is exactly one more than the floor. Moreover, (using truncating integer division, as in C or Java) floor(232 / n) == floor((232 - 1) / n)
. So the desired step is (232 - 1)/n + 1
.
n is a power of 2. In this case, n precisely divides 232
, and so (232 - 1) / n
will be one less than 232 / n
. So the desired step is (232 - 1)/n + 1
. Conveniently, that's the same value as in the first case.
Note: As @greybeard notes in a comment, there no guarantee that an appropriate step size exists if n > 216
. For larger n
, the above procedure will compute the largest step size which guarantees that overflow will not occur before step n
.
Upvotes: 4
Reputation: 28278
If you are using C as your programming language, you can use its unsigned arithmetic. Consider the following:
floor(232 / n) = floor((232 - n) / n + 1)
If your n
has an unsigned type (e.g. uint32_t
), then the mathematical expression 232 - n
can be calculated as simply -n
.
So in C:
uint32_t n = ...;
uint32_t d = (-n) / n + 1;
Alternatively:
uint32_t d = (0 - n) / n + 1;
You should document it well, because this is really obscure code.
Upvotes: 1