如何将二进制(字符串)转换为浮点值?

时间:2012-01-05 23:53:26

标签: python python-3.x

我想将二进制数转换为浮点数。这是一个可能性的例子:

>>> float(-0b1110)

给了我正确的输出:

-14.0

不幸的是,我正在处理二进制字符串,即我需要类似float('-0b1110')的内容。
但是,这不起作用:

>>> float('-0b1110')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for float(): -0b1110

我尝试使用binascii.a2b_qp(string[, header])将引用可打印数据块转换回二进制并返回二进制数据。但最终,我得到了同样的错误:

>>> float(binascii.a2b_qp('-0b1110'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for float(): -0b1110

我理解输出数是整数的情况,但如果我想获得数字12.546呢?函数调用二进制字符串会是什么样的呢?

6 个答案:

答案 0 :(得分:13)

在您的一条评论中,您指出二进制数表示8字节长IEEE 754二进制64格式的浮点数。但是,这与您作为示例显示的-0b1110值不一致,所以我忽略了它,并使用我自己的格式作为示例输入数据,用于测试下面显示的答案。

基本上所做的是首先将二进制字符串转换为整数值,然后将其转换为原始字节字符串,然后传递给struct.unpack()以便最终转换为浮点值。下面显示的 bin_to_float() 功能可以推动这一过程。尽管未示出,但二进制输入字符串参数可以以'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)

输出:

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

答案 1 :(得分:8)

另一个选择是

from ast import literal_eval

float_str = "-0b101010101"
result = float(literal_eval(float_str))

与内置的“eval”不同,literal_eval甚至可以在用户输入上运行,因为它只能解析Python文字 - 并且不会执行表达式,这意味着它也不会调用函数。

答案 2 :(得分:6)

float(int('-0b1110',0))

这适合我。

如果你有一个表示浮点数而不是整数的64位字符串,你可以进行三步转换 - 第一步将字符串转换为整数,第二步将其转换为8字节string,第三个将这些位重新解释为float。

>>> import struct
>>> s = '0b0100000000101001000101111000110101001111110111110011101101100100'
>>> q = int(s, 0)
>>> b8 = struct.pack('Q', q)
>>> struct.unpack('d', b8)[0]
12.546

当然,您可以将所有这些步骤合并为一行。

>>> s2 = '0b1100000000101100000000000000000000000000000000000000000000000000'
>>> struct.unpack('d', struct.pack('Q', int(s2, 0)))[0]
-14.0

答案 3 :(得分:2)

这对我有用。 用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

答案 4 :(得分:-1)

您可以使用eval('')然后根据需要将其转换为浮点数。示例:

>> eval('-0b1110')
-14
>> float(eval('-0b1110'))
-14.0

答案 5 :(得分:-1)

您可以通过在内置int([x[, base]])函数中将基数设置为2来将字符串形式的二进制数转换为int,但是您需要首先删除0b。然后,您可以将结果传递到float()以获得最终结果:

>>> s = '-0b1110'
>>> float(int(s.replace('0b', ''), 2))
-14.0

编辑:只有在Python 2.5及更低版本上才能显示摆脱0b,Mark的答案在Python 2.6上对我有用,但这是我在Python 2.5上看到的:

>>> int('-0b1110', 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 2: '-0b1110'