how to get the thighest bit position in big integers?
Nick Mellor
nick-groups at back-pain-self-help.com
Wed Oct 29 02:26:50 EDT 2008
On Oct 6, 3:40 am, Gary Herron <gher... at islandtraining.com> wrote:
> mmgar... at gmx.de wrote:
> > Hi,
>
> > I'm using python to develop some proof-of-concept code for a
> > cryptographic application. My code makes extended use of python's
> > native bignum capabilities.
>
> > In many cryptographic applications there is the need for a function
> > 'get_highest_bit_num' that returns the position number of the highest
> > set bit of a given integer. For example:
>
> > get_highest_bit_num( (1 << 159)) == 159
> > get_highest_bit_num( (1 << 160) - 1) == 159
> > get_highest_bit_num( (1 << 160)) == 160
>
> How about a binary search?
>
>
>
> >>> from bisect import bisect
> >>> BITS = [1<<n for n in range(1,1000)] # Use max number of bits here.
> >>> bisect(BITS, 1<<159)
> 159
> >>> bisect(BITS, 1<<160-1)
> 159
> >>> bisect(BITS, 1<<160)
> 160
>
> I have no clue if this is faster or not. The comparison function used
> in the search is (potentially) slow, but the search is O(log n) on the
> number of bits rather than O(n), so its worth a test.
>
> If you run timing test, let us know the results.
>
> Gary Herron
>
> > I implemented this the following way:
>
> > def get_highest_bit_num(r):
> > i = -1
> > while r > 0:
> > r >>= 1
> > i = i + 1
> > return i
>
> > This works, but it is a very unsatisfying solution, because it is so
> > slow.
>
> > My second try was using the math.log function:
>
> > import math
> > r = (1 << 160) - 1
> > print highest_bit_num(r) # prints out 159
> > print math.floor(math.log(r, 2)) # prints out 160.0
>
> > We see that math.log can only serve as a heuristic for the highest bit
> > position. For small r, for example r = (1 << 16) - 1, the result from
> > math.log(, 2) is correct, for big r it isn't any more.
>
> > My question to the group: Does anyone know of a non-hackish way to
> > determine the required bit position in python? I know that my two
> > ideas
> > can be combined to get something working. But is there a *better* way,
> > that isn't that hackish?
>
> > cheers,
> > mmg
> > --
> >http://mail.python.org/mailman/listinfo/python-list
>
>
The following might be worth a try. It's faster the fewer set bits
there are in the original number, and lightning fast if there are only
one or two:
def get_highest_bit_num(i):
while i>0: highestbit, i = i, i & (i-1)
return highestbit
>>> highestbit(1<<31)
2147483648L
>>> highestbit(1<<4)
16
>>> highestbit(3<<4)
32
Note that it returns the value of the highest bit, not its position.
All it's doing is successively ANDing i with (i-1) until i is zero,
then returning the previous value of i.
It works because i & (i-1) has a useful property: it returns i less
its least significant set bit:
i=6 (binary 110) => i & (i-1)==4 (binary 100)
i=3328 => (binary 1101_0000_0000) then i & (i-1)==3072 (binary
1100_0000_0000)
(underscores for readability)
As far as I know there isn't another piece of logic that helps you
extract the most significant bit as simply :-)
Best wishes,
Nick
More information about the Python-list
mailing list