代码之家  ›  专栏  ›  技术社区  ›  scribe

从python浮点类型到IEEE 64位浮点数组再回到python 3的最佳方式是什么?[重复]

  •  0
  • scribe  · 技术社区  · 5 年前

    如何将字符串作为32位浮点的二进制IEEE 754表示?

    实例

    1.00->'00111111100000000000000000000000'

    0 回复  |  直到 10 年前
        1
  •  82
  •   Richard    5 年前

    你可以用 struct 包裹:

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

    它将其打包为网络字节顺序浮点,然后将每个结果字节转换为8位二进制表示形式,并将它们连接起来:

    >>> binary(1)
    '00111111100000000000000000000000'
    

    编辑 : 有人要求扩大解释范围。我将使用中间变量来对每一步进行注释。

    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)
    

    下面是几个例子的结果:

    >>> 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'
    
        2
  •  40
  •   mgilson    8 年前

    这是一个丑陋的。。。

    >>> import struct
    >>> bin(struct.unpack('!i',struct.pack('!f',1.0))[0])
    '0b111111100000000000000000000000'
    

    基本上,我只是用struct模块将float转换成int。。。


    这里有一个稍微好一点的 ctypes :

    >>> import ctypes
    >>> bin(ctypes.c_uint.from_buffer(ctypes.c_float(1.0)).value)
    '0b111111100000000000000000000000'
    

    基本上,我构建了一个 float 使用相同的内存位置,但我将其标记为 c_uint 库因特 的值是一个python整数,可以使用内置的 bin 功能开启。

        3
  •  30
  •   funnydman    5 年前

    使用 bitstring 单元

    import bitstring
    f1 = bitstring.BitArray(float=1.0, length=32)
    print(f1.bin)
    

    输出:

    00111111100000000000000000000000
    
        4
  •  13
  •   Eric    9 年前

    为了完整性起见,您可以使用numpy实现这一点:

    f = 1.00
    int32bits = np.asarray(f, dtype=np.float32).view(np.int32).item()  # item() optional
    

    然后可以使用 b 格式限定符

    print('{:032b}'.format(int32bits))
    
        5
  •  10
  •   Mark Ransom    5 年前

    通过将问题分成两部分,可以更清晰地处理这个问题。

    第一种方法是将浮点转换为具有等效位模式的整数:

    import struct
    def float32_bit_pattern(value):
        return sum(ord(b) << 8*i for i,b in enumerate(struct.pack('f', value)))
    

    Python 3不需要 ord 要将字节转换为整数,需要将上面的内容简化一点:

    def float32_bit_pattern(value):
        return sum(b << 8*i for i,b in enumerate(struct.pack('f', value)))
    

    接下来,将int转换为字符串:

    def int_to_binary(value, bits):
        return bin(value).replace('0b', '').rjust(bits, '0')
    

    现在将它们结合起来:

    >>> int_to_binary(float32_bit_pattern(1.0), 32)
    '00111111100000000000000000000000'
    
        6
  •  9
  •   JavDomGom    6 年前

    通过这两个简单的函数( Python>=3.6 )对于IEEE 754 binary64,您可以轻松地将浮点数转换为二进制数,反之亦然。

    import struct
    
    def bin2float(b):
        ''' Convert binary string to a float.
    
        Attributes:
            :b: Binary string to transform.
        '''
        h = int(b, 2).to_bytes(8, byteorder="big")
        return struct.unpack('>d', h)[0]
    
    
    def float2bin(f):
        ''' Convert float to 64-bit binary string.
    
        Attributes:
            :f: Float number to transform.
        '''
        [d] = struct.unpack(">Q", struct.pack(">d", f))
        return f'{d:064b}'
    

    例如:

    print(float2bin(1.618033988749894))
    print(float2bin(3.14159265359))
    print(float2bin(5.125))
    print(float2bin(13.80))
    
    print(bin2float('0011111111111001111000110111011110011011100101111111010010100100'))
    print(bin2float('0100000000001001001000011111101101010100010001000010111011101010'))
    print(bin2float('0100000000010100100000000000000000000000000000000000000000000000'))
    print(bin2float('0100000000101011100110011001100110011001100110011001100110011010'))
    

    输出为:

    0011111111111001111000110111011110011011100101111111010010100100
    0100000000001001001000011111101101010100010001000010111011101010
    0100000000010100100000000000000000000000000000000000000000000000
    0100000000101011100110011001100110011001100110011001100110011010
    1.618033988749894
    3.14159265359
    5.125
    13.8
    

    我希望你喜欢,它非常适合我。

        7
  •  5
  •   y.selivonchyk    6 年前

    Piggy在Dan的答案后面添加了蟒蛇3的彩色版本:

    import struct
    
    BLUE = "\033[1;34m"
    CYAN = "\033[1;36m"
    GREEN = "\033[0;32m"
    RESET = "\033[0;0m"
    
    
    def binary(num):
        return [bin(c).replace('0b', '').rjust(8, '0') for c in struct.pack('!f', num)]
    
    
    def binary_str(num):
        bits = ''.join(binary(num))
        return ''.join([BLUE, bits[:1], GREEN, bits[1:10], CYAN, bits[10:], RESET])
    
    
    def binary_str_fp16(num):
        bits = ''.join(binary(num))
        return ''.join([BLUE, bits[:1], GREEN, bits[1:10][-5:], CYAN, bits[10:][:11], RESET])
    
    x = 0.7
    print(x, "as fp32:", binary_str(0.7), "as fp16 is sort of:", binary_str_fp16(0.7))
    

    colored representation

        8
  •  2
  •   Community Mohan Dere    9 年前

    在浏览了很多类似的问题后,我写了一些东西,希望能达到我的目的。

    f = 1.00
    negative = False
    if f < 0:
        f = f*-1
        negative = True
    
    s = struct.pack('>f', f)
    p = struct.unpack('>l', s)[0]
    hex_data =  hex(p)
    
    scale = 16
    num_of_bits = 32
    binrep = bin(int(hex_data, scale))[2:].zfill(num_of_bits)
    if negative:
        binrep = '1' + binrep[1:]
    

    binrep 这就是结果。 每个部分都将被解释。


    f = 1.00
    negative = False
    if f < 0:
        f = f*-1
        negative = True
    

    如果为负数,则将数字转换为正数,并将变量负数设置为false。这是因为正数和负数的二进制表示之间的区别就在第一位,这是比用负数来计算整个过程中出现的错误更简单的方法。


    s = struct.pack('>f', f)                          #'?\x80\x00\x00'
    p = struct.unpack('>l', s)[0]                     #1065353216
    hex_data =  hex(p)                                #'0x3f800000'
    

    s 是二进制的十六进制表示形式 f .然而,它不是我需要的那种漂亮的形式。这就是p的作用。它是十六进制s的int表示,然后再进行一次转换,得到一个漂亮的十六进制。


    scale = 16
    num_of_bits = 32
    binrep = bin(int(hex_data, scale))[2:].zfill(num_of_bits)
    if negative:
        binrep = '1' + binrep[1:]
    

    scale 是十六进制的基数16。 num_of_bits 是32,因为float是32位的,所以稍后会使用它来用0填充额外的位置,以达到32。有密码吗 宾雷普 从…起 this question .如果数字是负数,只需更改第一位。


    我知道这很难看,但我没有找到一个好方法,我很快就需要它。欢迎评论。

        9
  •  2
  •   johnml1135    9 年前

    这比要求的要多一点,但当我找到这个条目时,这正是我所需要的。该代码将给出IEEE 754 32位浮点的尾数、基数和符号。

    import ctypes
    def binRep(num):
        binNum = bin(ctypes.c_uint.from_buffer(ctypes.c_float(num)).value)[2:]
        print("bits: " + binNum.rjust(32,"0"))
        mantissa = "1" + binNum[-23:]
        print("sig (bin): " + mantissa.rjust(24))
        mantInt = int(mantissa,2)/2**23
        print("sig (float): " + str(mantInt))
        base = int(binNum[-31:-23],2)-127
        print("base:" + str(base))
        sign = 1-2*("1"==binNum[-32:-31].rjust(1,"0"))
        print("sign:" + str(sign))
        print("recreate:" + str(sign*mantInt*(2**base)))
    
    binRep(-0.75)
    

    输出:

    bits: 10111111010000000000000000000000
    sig (bin): 110000000000000000000000
    sig (float): 1.5
    base:-1
    sign:-1
    recreate:-0.75
    
        10
  •  1
  •   kol    5 年前

    将浮点值转换为0。。1.

    def float_bin(n, places = 3): 
        if (n < 0 or n > 1):
            return "ERROR, n must be in 0..1"
        
        answer = "0."
        while n > 0:
            if len(answer) - 2 == places: 
                return answer
            
            b = n * 2
            if b >= 1:
                answer += '1'
                n = b - 1
            else:
                answer += '0'
                n = b
                
        return answer
    
        11
  •  0
  •   dkhammond    9 年前

    其中一些答案与Python 3编写的答案不一样,或者没有给出负浮点数的正确表示形式。我发现以下内容适合我(尽管这提供了我所需要的64位表示)

    def float_to_binary_string(f):
        def int_to_8bit_binary_string(n):
            stg=bin(n).replace('0b','')
            fillstg = '0'*(8-len(stg))
            return fillstg+stg
        return ''.join( int_to_8bit_binary_string(int(b)) for b in struct.pack('>d',f) )
    
        12
  •  0
  •   Somen Das    5 年前

    我做了一个非常简单的。请检查一下。如果你认为有什么错误,请告诉我。这对我来说很好。

    sds=float(input("Enter the number : "))
    sf=float("0."+(str(sds).split(".")[-1]))
    aa=[]
    
    while len(aa)<15:
        dd=round(sf*2,5)
        if dd-1>0:
            
            aa.append(1)
            sf=dd-1
            
        else:
            
            sf=round(dd,5)
            aa.append(0)
        
    des=aa[:-1]
    print("\n")
    AA=([str(i) for i in des])
    
    print("So the Binary Of : %s>>>"%sds,bin(int(str(sds).split(".")[0])).replace("0b",'')+"."+"".join(AA))
    

    或者如果是整数,只需使用 bin(integer).replace("0b",'')

        13
  •  -1
  •   Robert Hughes    10 年前

    你可以用这个。我认为最简单的比特表示格式:

    我的代码看起来像:

    def fto32b(flt):
    # is given a 32 bit float value and converts it to a binary string
    if isinstance(flt,float):
        # THE FOLLOWING IS AN EXPANDED REPRESENTATION OF THE ONE LINE RETURN
                #   packed = struct.pack('!f',flt) <- get the hex representation in (!)Big Endian format of a (f) Float
                #   integers = []
                #   for c in packed:
                #       integers.append(ord(c))    <- change each entry into an int
                #   binaries = []
                #   for i in integers:
                #       binaries.append("{0:08b}".format(i)) <- get the 8bit binary representation of each int (00100101)
                #   binarystring = ''.join(binaries) <- join all the bytes together
                #   return binarystring
        return ''.join(["{0:08b}".format(i) for i in [ord(c) for c in struct.pack('!f',flt)]])
    return None
    

    输出:

    >>> a = 5.0
    '01000000101000000000000000000000'
    >>> b = 1.0
    '00111111100000000000000000000000'