The -bit binary counter is a boolean array A[0...k-1] that stores a number in binary, with A[0] as the least significant bit.

  • Initially all bits are 0 (i.e. the counter is 0).
  • Each index b represents the bit for

The structure supports one operation: increment(), which adds .

Increment Operation
b = 0
while b < k and A[b] == 1:
    A[b] = 0  # unset bit
    b = b + 1
if b < k:
    A[b] = 1  # set bit

This operation flips some number of consecutive 1s to 0, and then sets the first found 0 to 1. This sequence mimics addition by carrying the 1 to the next iteration (bit).

Worst-Case Analysis Of increment()

The run length is the number of iterations of the while loop in increment(), i.e., the number of consecutive 1s before the first 0.

The true cost of increment() is thus proportional to the run length.

  • The worst-case run length is , so the worst-case time per operation is .
  • Over increments, this gives a pessimistic bound of .

While some increments flip many bits (are costly), amortised analysis shows that the average cost per increment is low.

The run length is not necessarily equal to the true cost, as it doesn't account for setting the first found 0 to 1

Aggregate Method On K-Bit Binary Counter

To apply this method, we analyse how often each bit flips over n increments. The key idea is to group operations by their run length, i.e., the number of consecutive 1s before the first 0.

  • run_length = 0
    • These are the cases where A[0] = 0, requiring just setting A[0] = 1 ( unit of effort)
    • This happens for even values, which are half the numbers.
    • Therefore, there are counter values with A[0] = 0 (approximate as it depends on where the counter stops)
  • run_length = 1
    • Considering the remaining values (odd numbers), all of them have a 1 in their LSD.
    • But of those values, half are of the form of the form ...11, and the other half is ...01
    • run_length = 1 are counter values with A[0] = 1 and A[1] = 0 requiring flipping A[0] to 0 in the iterations, and setting A[1] to 1 at the end (2 units of effort)
    • Therefore, there are counter values

Extending this logic (up to ), results in:

Run Length
Values

To compute the total cost, multiply each group count by its respective effort.

Run Length
Values
Units Of Effort unit units units units units units
Respective Effort

For example, values with run_length 1 require units of effort each, so total effort for those values is

Therefore, the sum of all efforts is

This infinite sum converges to :

However, the counts are approximate (rounded down), the actual sequence of increments may end before reaching very large run lengths, and the summation ignores any partial increments or leftover bits.

Therefore, this sum provides an upper bound on the total cost:

Hence, the total time over increments is , and the amortized cost per increment is:

Accounting Method On K-Bit Binary Counter

To apply this method to the increment operation, we break it down into two atomic tasks:

  1. The task of flipping a bit from 1 to 0
    • This step occurs inside the while loop and may repeat multiple times per operation.
    • This only happens to bits that were previously set (= 1).
    • Each iteration (i.e. each flip) takes time.
  2. The task of setting a bit from 0 to 1
    • This happens once per increment, after exiting the loop.
    • It also takes time.
    • It runs at most once, as if all bits are already 1 (i.e. the counter is at ), the loop clears all bits and no 1 is set.

The key is to assign enough coins per increment so that each operation can:

  • Pay for its own flipping and setting costs.
  • Save extra coins as credit when setting bits to 1, which can later be used to pay for flipping those bits back to 0 in future operations.

Assume that coin pays for effort during any part of the increment operation.

Then coin can be allocated each time a bit is set to 1 (just before A[b] = 1 executes).

The coins are then used as follows:

  • coin is then used for the actual bit-setting
  • The remaining coins are stored as credit on that bit for future use.

Later, when the bit is flipped from 1 to 0 (in the loop) during a future increment, this credit is then used to pay:

  • Each iteration of the loop flips a bit to 0, costing coin per iteration
  • Since each set bit has coins stored on it, we can afford to flip it up to coins

Thus, as long as there’s coins, there’s always enough credit to cover all future un-sets. This ensures:

  • No operation goes into debt
  • The total amortised cost is bounded by coins per increment, which is .

Potential Method On K-Bit Binary Counter

We define a potential function as the number of bits set to 1 in the counter after the -th increment operation.

  • represents the “stored work”, each 1 will eventually need to be flipped back to 0, costing one unit each.
  • Initially, the counter is all zeroes, so .
  • In general, for all , and the maximum potential is when all bits are set.

Let’s analyse the amortised cost of one increment() operation:

  • When an increment() is performed, several bits may flip from 1 to 0, and exactly one bit flips from 0 to 1.
  • Suppose the number of 1 -> 0 transitions is (i.e., the number of iterations of the while loop).
  • Then, the total number of bit operations is .

The change in potential is thus:

  • If , then
  • If , then

From the amortised cost:

Substituting the two expressions into it results in:

In both cases, , so the amortised cost per operation is . Over increments, the total amortised time is .