Round (floor) to the nearest member of the geometric sequence (2, 4, 8, 16, 32, 64, 128 . . . )?

Question:

As the title explains, how could I create a function func (using numpy or math modules) to find the nearest member of the geometric sequence (2, 4, 8, 16, 32, 64, 128 . . . )?

For example, func(3) should yield 2, func(20) should yield 16, and func(128) should yield 128.

I cannot find any information on this problem. Most rounding problems discuss rounding to the nearest multiple of some number, rather than to the nearest member of a geometric sequence.

Asked By: Timothy

||

Answers:

Use the concept of power and log

import numpy as np
def round_to_geometric(x):
    return int(2 ** np.floor(np.log2(x)))

output:

> print(round_to_geometric(3))
> print(round_to_geometric(20))
> print(round_to_geometric(128))

2
16
128
Answered By: JayPeerachai

One way to think about this is in terms of the length of a binary representation of an integer:

def myround(i):
  return 2 ** (len(bin(i)) - 3)
>>> [myround(i) for i in (3, 4, 5, 6, 7, 8, 20, 25, 128)]
[2, 4, 4, 4, 4, 8, 16, 16, 128]

Explanation: bin(x) returns a binary string representation of the input.

>>> bin(20)
'0b10100'

The length of this representation depends on the most significant bit in the sequence. For bin(20), the most significant bit is 16 (or 2 ** 4). Subtracting 3 ignores the 0b and the 1s place in the binary string. So len(bin(20)) - 3 = 4

Answered By: Alexander L. Hayes
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.