Float to binary

前端 未结 6 2145
醉话见心
醉话见心 2020-12-25 10:17

I\'m trying to convert a floating point number to binary representation; how can I achieve this? My goal is, however, not to be limited by 2m so I\'m hoping for something th

相关标签:
6条回答
  • 2020-12-25 10:38

    Next answer with a bit of theory.

    Explanation below does not explain IEEE Floating Point standard only general ideas concerning representation of floating point numbers

    Every float number is represented as a fractional part multiplied by an exponent multiplied by a sign. Additionally there is so called bias for exponent, which will be explained bellow.

    So we have

    1. Sign bit
    2. Fractional part digits
    3. Exponent part digits

    Example for base 2 with 8 bit fraction and 8 bit exponent

    Bits in fraction part tell us which summands (numbers to be added) from sequence below are to be included in represented number value

    2^-1 + 2^-2 + 2^-3 + 2^-4 + 2^-5 + 2^-6 + 2^-7 + 2^-8

    So if you have say 01101101 in fractional part it gives

    0*2^-1 + 1*2^-2 + 1*2^-3 + 0*2^-4 + 1*2^-5 + 1*2^-6 + 0*2^-7 + 1*2^-8 = 0.42578125

    Now non-zero numbers that are representable that way fall between 2 ** -8 = 0.00390625 and 1 - 2**-8 = 0.99609375

    Here the exponent part comes in. Exponent allows us to represent very big numbers by multiplying the fraction part by exponent. So if we have an 8bit exponent we can multiply the resulting fraction by numbers between 0 and 2^255.

    So going back to example above let's take exponent of 11000011 = 195.

    We have fractional part of 01101101 = 0.42578125 and exponent part 11000011 = 195. It gives us the number 0.42578125 * 2^195, this is really big number.

    So far we can represent non-zero numbers between 2^-8 * 2^0 and (1-2^-8) * 2^255. This allows for very big numbers but not for very small numbers. In order to be able to represent small numbers we have to include so called bias in our exponent. It is a number that will be always subtracted from exponent in order to allow for representation of small numbers.

    Let's take a bias of 127. Now all exponents are subtracted 127. So numbers that can be represented are between 2^-8 * 2^(0 - 127) and (1-2^-8) * 2^(255 - 127 = 128)

    Example number is now 0.42578125 * 2^(195-127 = 68) which is still pretty big.

    Example ends

    In order to understand this better try to experiment with different bases and sizes for fractional and exponential part. At beginning don't try with odd bases because it only complicates things necessary.

    Once you grasp how this representation works you should be able to write code to obtain representation of any number in any base, fractional/exponential part combination.

    0 讨论(0)
  • 2020-12-25 10:41

    This isn't the same style of binary representation that you want, but this will convert an IEEE 754 into it's sign, mantissa and base, which can be used to create a hex representation in a fairly straightforward fashion. Note that the 'value' of the mantissa is 1+BINARY, where BINARY is the binary representation - hence the -1 in the return.

    I wrote this code and am declaring it public domain.

        def disect_float(f):
          f = float(f); #fixes passing integers
          sign = 0x00; #positive
          exp = 0;
          mant = 0;
          if(f < 0): #make f positive, store the sign
            sign = '-'; #negative
            f = -f;
          #get the mantissa by itself
          while(f % 1 > 0): #exp is positive
            f*=2
            exp+=1
          #while(f % 1 > 0):
          tf = f/2;
          while(tf % 1 <= 0): #exp is negative
            exp-=1;
            f=tf;
            tf=f/2;
            if(exp < -1024): break;
          mant=int(f);
          return sign, mant-1, exp;
    
    0 讨论(0)
  • 2020-12-25 10:42

    For floats there is built-in method hex().

    http://docs.python.org/library/stdtypes.html#float.hex

    It gives you the hexadecimal representation of a given number. And translation form hex to binary is trivial.

    For example:

    In [15]: float.hex(1.25)
    Out[15]: '0x1.4000000000000p+0'
    
    In [16]: float.hex(8.25)
    Out[16]: '0x1.0800000000000p+3'
    
    0 讨论(0)
  • 2020-12-25 10:51

    If you want to convert a float to a string with d digits after the decimal radix point:

    1. Multiply the number by base**d.
    2. Round to the nearest integer.
    3. Convert the integer to a string.
    4. Insert the . character d digits before the end.

    For example, to represent 0.1 in base 12 with 4 decimal dozenal places,

    1. 0.1 × 124 = 2073.6
    2. Round to nearest integer → 2074
    3. Convert to string → 124A
    4. Add radix point → 0.124A
    0 讨论(0)
  • 2020-12-25 10:58

    Answering the title directly and using float.hex, which uses 64bit IEE754, one could write this method:

    def float_to_bin(x):
      if x == 0:
        return "0" * 64
      w, sign = (float.hex(x), 0) if x > 0 else (float.hex(x)[1:], 1)
      mantissa, exp = int(w[4:17], 16), int(w[18:])
      return "{}{:011b}{:052b}".format(sign, exp + 1023, mantissa)
    
    float_to_bin(-0.001) # '1011111101010000000010110011111101011000011011100110110100101010'
    

    Note however, this does not work for NaN and Inf.

    0 讨论(0)
  • 2020-12-25 11:02

    There is one trick that i observed that we can do using simple string manipulations. I felt this method to be simpler than other methods that i came across.

    s = "1101.0101"
    s1, s2 = s.split(".")
    s1 = int(s1, 2)
    s2 = int(s2, 2)/(2**len(s2))
    x = s1+s2
    print(x)
    

    Output :

    13.3125
    

    Hope it will be helpful to someone.

    0 讨论(0)
提交回复
热议问题