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
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
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.
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;
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'
If you want to convert a float
to a string with d
digits after the decimal radix point:
base**d
..
character d
digits before the end.For example, to represent 0.1 in base 12 with 4 decimal dozenal places,
124A
0.124A
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.
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.