Does Python allow access to some of the implementation details?

Claudio Grondi claudio.grondi at freenet.de
Fri Jan 6 16:09:41 EST 2006


casevh at comcast.net wrote:
> I don't know of a way to directly access the internal structure of a
> long, but you can speed up your example.
> 
> First, is the order of the commands
> 
> 
>>  i=i>>1
>>  lstBitsBitwiseAnd.append(i&0x01)
> 
> 
> what you intend? The first low order bit is discarded because you've
> done the shift first. And an extra 0 is appended.
> 
> If you are trying to get the binary representation of a long, try
> i.__hex__(). This will create a string with the hex representation.
> Conversion from hex to binary is left as an exercise for the reader. :-)
> 
You are right, it is not correct if you want to get all bits out of an 
integer value. I haven't payed attention to the proper order, because my 
only intent was to check what is faster modulo-division or bitwise-and, 
so for the outcome of this the order does not matter.

The i.__hex__() idea is very, very near to what I have originally asked 
for. It's a pity, that it can't be generally considered faster than 
usage of shifting+bitwise-and where the latter seem to be superior for 
small long integers and integers (see attached code showing a break even 
for integers which require more than appr. 16 up to 104 digits according 
to multiple tests on my machine).

Claudio

import time

dctLstOfBitsVsCharOfNibble = {}
# dctLstOfBitsVsCharOfNibble is a dictionary with a key beeing one 
character
# string representing hexadecimal value of a nibble and a value beeing a 
list
# of bits of the nibble where the lowest bit is stored at index 0 of the 
list.
# i.e.
dctLstOfBitsVsCharOfNibble = {
   '0':[0, 0, 0, 0],
   '1':[0, 0, 0, 1],
   '2':[0, 0, 1, 0],
   '3':[0, 0, 1, 1],
   '4':[0, 1, 0, 0],
   '5':[0, 1, 0, 1],
   '6':[0, 1, 1, 0],
   '7':[0, 1, 1, 1],
   '8':[1, 0, 0, 0],
   '9':[1, 0, 0, 1],
   'A':[1, 0, 1, 0],
   'B':[1, 0, 1, 1],
   'C':[1, 1, 0, 0],
   'D':[1, 1, 0, 1],
   'E':[1, 1, 1, 0],
   'F':[1, 1, 1, 1]
}
# The dictionary can also be generated e.g. using following code:
# dctLstOfBitsVsCharOfNibble = {}
# for intNibbleValue in range(0, 16):
#   lstBitReprOfCurrNibble=[]
#   for indxOfBit in range(0,4):
#     lstBitReprOfCurrNibble.append(intNibbleValue>>indxOfBit&0x01)
#   #:for
#   lstBitReprOfCurrNibble.reverse()
# 
dctLstOfBitsVsCharOfNibble['%X'%(intNibbleValue,)]=lstBitReprOfCurrNibble
# #:for

NoOf32bitChunksOfInteger = 0
n = 0
lstBitsBitwiseAnd = []
lstBitsModulo     = []
lstBitsViaHex     = []
timeBitwiseAnd   = -1
timeModulo       = -1
timeBitsViaHex   = -1

while timeBitwiseAnd <= timeBitsViaHex:

   n = (n<<32) + 0x12345678
   NoOf32bitChunksOfInteger += 1

   i = n
   lstBitsModulo = []
   start = time.clock()
   while i:
     lstBitsModulo.append(i%2)
     i=i>>1
   timeModulo = time.clock()-start

   i = n
   lstBitsBitwiseAnd = []
   start = time.clock()
   while i:
     lstBitsBitwiseAnd.append(i&0x01)
     i=i>>1
   timeBitwiseAnd = time.clock()-start

   i = n
   # lstBitsViaHex = []
   start = time.clock()
   strHexOf_i = i.__hex__()[2:]
   if strHexOf_i[-1]=='L':
     strHexOf_i=strHexOf_i[0:-1]
   #:if
   intNoOfLeadingZeroBits = 0
   lstBitsOfFirstNibble = dctLstOfBitsVsCharOfNibble[strHexOf_i[0]]
   while not lstBitsOfFirstNibble[intNoOfLeadingZeroBits] and 
intNoOfLeadingZeroBits < 4:
     intNoOfLeadingZeroBits += 1
   #:while
   if intNoOfLeadingZeroBits == 4:
     lstBitsViaHex = []
   else:
     lstBitsViaHex = lstBitsOfFirstNibble[intNoOfLeadingZeroBits:]
   #:if
   for indxToStrHexOf_i in range(1,len(strHexOf_i)):
     lstBitsViaHex += 
dctLstOfBitsVsCharOfNibble[strHexOf_i[indxToStrHexOf_i]]
   #:for
   lstBitsViaHex.reverse()
   timeBitsViaHex = time.clock()-start
#:while

if lstBitsBitwiseAnd == lstBitsModulo and lstBitsBitwiseAnd == 
lstBitsViaHex:
   print
   print '  Seconds for bit extraction from integer with %i hex-digits 
when: '%(NoOf32bitChunksOfInteger*8,)
   print
   print '      looping over i>>1;i&0x01 = %f '%(timeBitwiseAnd,)
   print '      looping over i>>1;i%%2    = %f '%(timeModulo,)
   print '      using i.__hex__() repr.  = %f '%(timeBitsViaHex,)
   print
   print '  For long integers  i  with number of hexadecimal digits '
   print '      > %i '%(NoOf32bitChunksOfInteger*8,)
   print '  bits extraction with i.__hex__() is faster then with 
i>>1;i&0x01 .'
   print
   print '  Modulo division (%) is always much slower than bitwise and 
(&). '





More information about the Python-list mailing list