Obtain & manipulate bit pattern of float as integer
The problem is that a Python float object might not be a IEEE 754, because it is an object (in fact they are, but internally they could hold whichever representation is more convenient)...
As leo said, you can do a type cast with ctypes, so you are enforcing a particular representation (in this case, single precision):
from ctypes import *
x = 173.3125
bits = cast(pointer(c_float(x)), POINTER(c_int32)).contents.value
print hex(bits)
#swap the least significant bit
bits ^= 1
And then back:
y = cast(pointer(c_int32(bits)), POINTER(c_float)).contents.value
You can get the string you want (apparently implying a big-endian, 32-bit representation; Python internally uses the native endianity and 64-bits for floats) with the struct
module:
>>> import struct
>>> x = 173.125
>>> s = struct.pack('>f', x)
>>> ''.join('%2.2x' % ord(c) for c in s)
'432d2000'
this doesn't yet let you perform bitwise operations, but you can then use struct again to map the string into an int:
>>> i = struct.unpack('>l', s)[0]
>>> print hex(i)
0x432d2000
and now you have an int
which you can use in any sort of bitwise operations (follow the same two steps in reverse if after said operations you need to get a float
again).
For reference, it is also possible to use numpy and view.
import numpy
def fextract( f ):
bits = numpy.asarray( f, dtype=numpy.float64 ).view( numpy.int64 )
if not bits & 0x7fffffffffffffff: # f == +/-0
return 0, 0
sign = numpy.sign(bits)
exponent = ( (bits>>52) & 0x7ff ) - 1075
mantissa = 0x10000000000000 | ( bits & 0xfffffffffffff )
# from here on f == sign * mantissa * 2**exponent
for shift in 32, 16, 8, 4, 2, 1:
if not mantissa & ((1<<shift)-1):
mantissa >>= shift
exponent += shift
return sign * mantissa, exponent
fextract( 1.5 ) # --> 3, -1