pythonbinaryfloating-point

Binary representation of float in Python (bits not hex)


How can I get a string of 0s and 1s, according to the bits of the IEEE 754 representation of a 32 bit float?

For example, given an input 1.00, the result should be '00111111100000000000000000000000'.


Solution

  • You can do that with the struct package:

    import struct
    def binary(num):
        return ''.join('{:0>8b}'.format(c) for c in struct.pack('!f', num))
    

    That packs it as a network byte-ordered float, and then converts each of the resulting bytes into an 8-bit binary representation and concatenates them out:

    >>> binary(1)
    '00111111100000000000000000000000'
    

    Edit: There was a request to expand the explanation. I'll expand this using intermediate variables to comment each step.

    def binary(num):
        # Struct can provide us with the float packed into bytes. The '!' ensures that
        # it's in network byte order (big-endian) and the 'f' says that it should be
        # packed as a float. Alternatively, for double-precision, you could use 'd'.
        packed = struct.pack('!f', num)
        print 'Packed: %s' % repr(packed)
    
        # For each character in the returned string, we'll turn it into its corresponding
        # integer code point
        # 
        # [62, 163, 215, 10] = [ord(c) for c in '>\xa3\xd7\n']
        integers = [ord(c) for c in packed]
        print 'Integers: %s' % integers
    
        # For each integer, we'll convert it to its binary representation.
        binaries = [bin(i) for i in integers]
        print 'Binaries: %s' % binaries
    
        # Now strip off the '0b' from each of these
        stripped_binaries = [s.replace('0b', '') for s in binaries]
        print 'Stripped: %s' % stripped_binaries
    
        # Pad each byte's binary representation's with 0's to make sure it has all 8 bits:
        #
        # ['00111110', '10100011', '11010111', '00001010']
        padded = [s.rjust(8, '0') for s in stripped_binaries]
        print 'Padded: %s' % padded
    
        # At this point, we have each of the bytes for the network byte ordered float
        # in an array as binary strings. Now we just concatenate them to get the total
        # representation of the float:
        return ''.join(padded)
    

    And the result for a few examples:

    >>> binary(1)
    Packed: '?\x80\x00\x00'
    Integers: [63, 128, 0, 0]
    Binaries: ['0b111111', '0b10000000', '0b0', '0b0']
    Stripped: ['111111', '10000000', '0', '0']
    Padded: ['00111111', '10000000', '00000000', '00000000']
    '00111111100000000000000000000000'
    
    >>> binary(0.32)
    Packed: '>\xa3\xd7\n'
    Integers: [62, 163, 215, 10]
    Binaries: ['0b111110', '0b10100011', '0b11010111', '0b1010']
    Stripped: ['111110', '10100011', '11010111', '1010']
    Padded: ['00111110', '10100011', '11010111', '00001010']
    '00111110101000111101011100001010'