Python 中浮点数的二进制表示(位而非十六进制)

2025-02-18 09:23:00
admin
原创
110
摘要:问题描述:如何根据 IEEE 754 对 32 位浮点数的表示,获取0s 和s的字符串?1例如,给定输入1.00,结果应该是'00111111100000000000000000000000'。解决方案 1:您可以使用以下包来实现struct:import struct def binary(num): ...

问题描述:

如何根据 IEEE 754 对 32 位浮点数的表示,获取0s 和s的字符串?1

例如,给定输入1.00,结果应该是'00111111100000000000000000000000'


解决方案 1:

您可以使用以下包来实现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 '>xa3xd7
']
    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: '?x80x00x00'
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: '>xa3xd7
'
Integers: [62, 163, 215, 10]
Binaries: ['0b111110', '0b10100011', '0b11010111', '0b1010']
Stripped: ['111110', '10100011', '11010111', '1010']
Padded: ['00111110', '10100011', '11010111', '00001010']
'00111110101000111101011100001010'

解决方案 2:

这是一个丑陋的......

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

基本上,我只是使用 struct 模块将浮点数转换为整数...


这是一个稍微好一点的使用ctypes

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

基本上,我构造一个float并使用相同的内存位置,但我将其标记为c_uint32c_uint32的值是一个python整数,您可以在其上使用内置bin函数。

注意:通过切换类型我们也可以进行反向操作

>>> ctypes.c_float.from_buffer(ctypes.c_uint32(int('0b111111100000000000000000000000', 2))).value
1.0

对于双精度 64 位浮点数,我们可以使用相同的技巧,即使用ctypes.c_double& ctypes.c_uint64

解决方案 3:

找到了另一个使用位串模块的解决方案。

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

输出:

00111111100000000000000000000000

解决方案 4:

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

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

然后,您可以使用b格式说明符打印此内容(带填充)

print('{:032b}'.format(int32bits))

解决方案 5:

使用这两个简单的函数(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

我希望你喜欢它,它对我来说非常完美。

解决方案 6:

将这个问题分成两部分可以更清楚地处理。

首先是将浮点数转换为具有等效位模式的整数:

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'

解决方案 7:

对 Dan 的答案进行改进,添加了 Python3 的彩色版本:

import struct

BLUE = ""
CYAN = ""
GREEN = ""
RESET = ""


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))

彩色表示

解决方案 8:

浏览了很多类似的问题后,我写了一些希望能满足我要求的东西。

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

如果数字为负数,则将其转换为正数,并将变量 negative 设置为 false。这样做的原因是正负二进制表示之间的差异仅在第一位,这比在使用负数执行整个过程时找出问题所在更简单。


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

s是二进制的十六进制表示f。但它不是我需要的漂亮形式。这就是 p 的作用所在。它是十六进制的 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,因为浮点数是 32 位,所以稍后会用 0 填充额外的位置以达到 32。从这个问题binrep中获取了代码。如果数字为负数,只需更改第一位。


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

解决方案 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:

在 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:

这些答案中有几个在 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:

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

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("
")
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:

在我看来,您可以使用 .format 来最简单地表示位:

我的代码看起来像:

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'

解决方案 14:

让我们使用 numpy!

import numpy as np

def binary(num, string=True):
    bits = np.unpackbits(np.array([num]).view('u1'))
    if string:
        return np.array2string(bits, separator='')[1:-1]
    else:
        return bits

例如,

binary(np.pi)
# '0001100000101101010001000101010011111011001000010000100101000000'

binary(np.pi, string=False)
# array([0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1,
#       0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0,
#       0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0],
#      dtype=uint8)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3911  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2721  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   61  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   61  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   54  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用