In one of your comments you indicated that the binary number represents a float in 8 byte long IEEE 754 binary64 format. However that is inconsistent with the -0b1110 value you showed as an example, so I've ignored it and used my own which is in the proper format as example input data for testing the answer shown below.
Essentially what is done is first the binary string is converted into an integer value, then next into a string of raw bytes which is passed to struct.unpack() for final conversion to a floating point value. The bin_to_float() function shown below drives the process. Although not illustrated, binary input string arguments can be prefixed with '0b'.
from codecs import decode
import struct
def bin_to_float(b):
""" Convert binary string to a float. """
bf = int_to_bytes(int(b, 2), 8) # 8 bytes needed for IEEE 754 binary64.
return struct.unpack('>d', bf)[0]
def int_to_bytes(n, length): # Helper function
""" Int/long to byte string.
Python 3.2+ has a built-in int.to_bytes() method that could be used
instead, but the following works in earlier versions including 2.x.
"""
return decode('%%0%dx' % (length << 1) % n, 'hex')[-length:]
def float_to_bin(value): # For testing.
""" Convert float to 64-bit binary string. """
[d] = struct.unpack(">Q", struct.pack(">d", value))
return '{:064b}'.format(d)
if __name__ == '__main__':
for f in 0.0, 1.0, -14.0, 12.546, 3.141593:
print('Test value: %f' % f)
binary = float_to_bin(f)
print(' float_to_bin: %r' % binary)
floating_point = bin_to_float(binary) # Round trip.
print(' bin_to_float: %f\n' % floating_point)
Output:
Test value: 0.000000
float_to_bin: '0000000000000000000000000000000000000000000000000000000000000000'
bin_to_float: 0.000000
Test value: 1.000000
float_to_bin: '0011111111110000000000000000000000000000000000000000000000000000'
bin_to_float: 1.000000
Test value: -14.000000
float_to_bin: '1100000000101100000000000000000000000000000000000000000000000000'
bin_to_float: -14.000000
Test value: 12.546000
float_to_bin: '0100000000101001000101111000110101001111110111110011101101100100'
bin_to_float: 12.546000
Test value: 3.141593
float_to_bin: '0100000000001001001000011111101110000010110000101011110101111111'
bin_to_float: 3.141593
Answer from martineau on Stack Overflowpython - How to convert a binary (string) into a float value? - Stack Overflow
Convert From binary to Float in C
Binary to Float?
What's a good way to convert from binary to float?
How do I convert a decimal to IEEE 754 binary?
How do I convert a number to floating-point?
To convert a decimal number to a floating-point representation, follow these steps:
- Convert the entire number to binary and then normalize it, i.e. write it in scientific notation using base 2.
- Truncate the fraction after the decimal point to the allowable fraction length.
- Extract the sign, exponent, and fraction segments.
Refer to the IEEE754 standard for more detailed instructions.
What is the difference between 32-bit and 64-bit floating point?
In one of your comments you indicated that the binary number represents a float in 8 byte long IEEE 754 binary64 format. However that is inconsistent with the -0b1110 value you showed as an example, so I've ignored it and used my own which is in the proper format as example input data for testing the answer shown below.
Essentially what is done is first the binary string is converted into an integer value, then next into a string of raw bytes which is passed to struct.unpack() for final conversion to a floating point value. The bin_to_float() function shown below drives the process. Although not illustrated, binary input string arguments can be prefixed with '0b'.
from codecs import decode
import struct
def bin_to_float(b):
""" Convert binary string to a float. """
bf = int_to_bytes(int(b, 2), 8) # 8 bytes needed for IEEE 754 binary64.
return struct.unpack('>d', bf)[0]
def int_to_bytes(n, length): # Helper function
""" Int/long to byte string.
Python 3.2+ has a built-in int.to_bytes() method that could be used
instead, but the following works in earlier versions including 2.x.
"""
return decode('%%0%dx' % (length << 1) % n, 'hex')[-length:]
def float_to_bin(value): # For testing.
""" Convert float to 64-bit binary string. """
[d] = struct.unpack(">Q", struct.pack(">d", value))
return '{:064b}'.format(d)
if __name__ == '__main__':
for f in 0.0, 1.0, -14.0, 12.546, 3.141593:
print('Test value: %f' % f)
binary = float_to_bin(f)
print(' float_to_bin: %r' % binary)
floating_point = bin_to_float(binary) # Round trip.
print(' bin_to_float: %f\n' % floating_point)
Output:
Test value: 0.000000
float_to_bin: '0000000000000000000000000000000000000000000000000000000000000000'
bin_to_float: 0.000000
Test value: 1.000000
float_to_bin: '0011111111110000000000000000000000000000000000000000000000000000'
bin_to_float: 1.000000
Test value: -14.000000
float_to_bin: '1100000000101100000000000000000000000000000000000000000000000000'
bin_to_float: -14.000000
Test value: 12.546000
float_to_bin: '0100000000101001000101111000110101001111110111110011101101100100'
bin_to_float: 12.546000
Test value: 3.141593
float_to_bin: '0100000000001001001000011111101110000010110000101011110101111111'
bin_to_float: 3.141593
This works for me. Tested with Python3.4:
def float_to_bin(num):
return bin(struct.unpack('!I', struct.pack('!f', num))[0])[2:].zfill(32)
def bin_to_float(binary):
return struct.unpack('!f',struct.pack('!I', int(binary, 2)))[0]
float_to_bin(bin_to_float(float_to_bin(123.123))) == float_to_bin(123.123)
>>> True
Hello,
i'm reciving 4 byte on a serial channel, this 4 byte are the binary of a float number, 1-bit for the sign, 8-bit for exponent, 23*-bit for the mantissa, my board recive them as 4 uint8. Now i want to convert them to float, how i can do it?
i want to convert uint8 val[4] to float.
Thanks for your time, and your help.
I'm trying to read binary data (binary representations of 32 bit float numbers) and convert them to floating point numbers.
What's a good way of doing this? I was looking into a function that did this but the two I have found are giving me strange results--one creates a 36 bit integer from a floating point number (tried some examples) and another can create an estimated floating point number but it doesn't seem to be very close to the real floating point number.
Assuming you are a looking for a single floating point here is the format:
First digit is sign, next 8 are the exponent and finally, the last 23 are the significand.
For your number (00111111010000000000000000000000)
Sign: 0 is +
Exponent: 01111110 is -1 (126-127)
Significand: 10000000000000000000000 is 1.5 (The 'invisible' first bit gives you 1, then the second bit (only one set) is 0.5, the next one would have been 0.25, then 0.125 and so on)
You then calculate the value as such:
sign * 2^exp * Significand
1 * 2^-1 * 1.5
1 * 0.5 * 1.5
0.75
You floating point number is equal to 0.75.
If you do some looking around at wikipedia and other places, what you will learn is that the floating point standards (there are different ones, IEEE754 being the most commonly known because it is used on desktops, etc (dsp's will have their own sometimes which are faster to compute)) will "normalize" the number. Floating point is all about where the decimal point is, a non-floating point integer has an implied decimal point to the right of the number
00111111010000000000000000000000. <--- here
other than all zeros to normalize lets assume we are using a format that wants the number to be 1.xxxx in binary so we need to move our decimal point
001.11111010000000000000000000000
the decimal place was moved just after the most significant one (so that only one 1 is to the left of the decimal point).
if you remember from math in high school 123 can be written as 1.23 * 10^2 (ten to the power 2). 123 is also 123 * 10^0. Each place that you move the decimal left in a base 10 number increases the power of 10 by one. Each place to the right decreases. No different in binary which is base 2, each place you move the decimal left you increase the power of 2 (binary is base 2) each place right, you decrease the power of 2.
So to be accurate our number is now
1.1111101 * 2^30
Now the details of the floating point format come into play. Because the 1 to the left of the decimal point (Except for the exact number zero and some other exceptions) is assumed to be there, it is sometimes not in the final binary representation for that floating point number, it is a waste of space to put a bit we know is always one when we could instead have one more bit for mantissa. The mantissas are often wysiwyg in the binary, the exponent is the one that leaves you scratching your head, esp with IEEE754. An exponent of 128 for example in the binary format for the number might represent 2 to the power 0 a 129 might be 2 to the power 1 and so on. this may seem strange but it is nothing more than a twos complement field for some of these formats, others have other ways do do things. Single, double, extended have different numbers of bits for the exponent and you need to figure out what you add to the real exponent (30 in this case) to get the bit pattern that goes in the exponent field of the floating point number.
another example
0000000000000000000000000000000000000101
would be
1.01 * 2^2
if you start with a 32 bit integer (not float) and want to end up with a 32 bit floating point number you obviously cannot retain all the detail of that number, since the floating point number needs a sign bit and an exponent as well as the mantissa, the mantissa is less than 32 bits so you throw away the least significant bits
1000000000000000000000000000001
will get chopped off at some point:
1.000000000000000 * 2^something
Suppose we can convert a binary integer to a decimal one repeatedly finding the remainder from dividing by ten and looking it up in a table of digits, that way for 10101 weโd first divide it by ten and get a remainder of 1 which maps to 1, then weโd divide it by ten once more and get a remainder of of 10, which maps to 2. That way weโd get 21.
But how would I get 0.75 from 0.11?