views:

161

answers:

3

I m doing this

def power_two(n, base = -1):
    result = 2 ** base
    if result < n:
        base += 1
        power_two(n, base)
    else:
        if result == n:
            print base
        else:
            print base - 1

what is the pythonic way to find largest power of two less than X number?

EDIT example: power_two(100) return only the power

+13  A: 

Use a logarithm, truncate it and then raise it to the power of 2:

def power_two(n):
    return 2**int(math.log(n, 2)))

Update: returning only the power:

def power_two(n):
    return int(math.log(n, 2))
Mark Byers
thank you, but I want this return 6 "2**6" instead 64
@mark: I mean return only 6, the "2**6" was to explain where the 6 come from, but you give me a pythonic way, thank you
@user422100: OK, I understand now.
Mark Byers
Of course, if `n <= 0` an exception is raised.
myle
In Python3.2: `int(math.log(4,2)) == 1`, but `int(math.log(8,2)) == 3`. It is an inconsistent behavior for `power_two()` function.
J.F. Sebastian
@myle, It's a feature.
Mike Graham
@Sebastian Probably it is a bug in Python 3.2. That would break compatibility with previous versions. Namely, Python 3.1.2 works as expected `math.log(4,2) = 2.0`.
myle
+2  A: 

Two ways, first works only in Python 2.7 and maybe 3+:

import random
for number in (random.randint(0,1<<32) for _ in range(16)):
    print "%20i,%4i, %4i" % (number, number.bit_length()-1, len(bin(number))-3)
Tony Veijalainen
The second approach using `bin` works in Python 2.6 or newer.
Mark Byers
+4  A: 

You could use bit_length():

def power_two(n):
    return n.bit_length() - 1

By definition for n != 0: 2**(n.bit_length()-1) <= abs(n) < 2**n.bit_length()

J.F. Sebastian
This is a nice solution, although actually Tony Veijalainen actually already posted it - it's just his answer is less clear. I gave my +1 to him for being first to suggest it and also for mentioning that it requires Python 2.7 or newer which is a very real concern - many users are still on Python 2.6.
Mark Byers
@Mark Byers: I've up-voted Tony Veijalainen as well (it was -1). Python 2.7 is the current version of CPython therefore I don't mention it explicitly (I use 2.4 at work so I understand where you're coming from). When I saw your answer I've thought that there must be some bit twiddling solution (MSB). `long.bits_in_digit()` is not public so `bit_length()` is the next best thing.
J.F. Sebastian