Python 中浮点数的二进制表示(位不是十六进制)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16444726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Binary representation of float in Python (bits not hex)
提问by TheMeaningfulEngineer
How to get the string as binary IEEE 754 representation of a 32 bit float?
如何将字符串作为 32 位浮点数的二进制 IEEE 754 表示?
Example
例子
1.00 -> '00111111100000000000000000000000'
1.00 -> '00111111100000000000000000000000'
采纳答案by Dan Lecocq
You can do that with the structpackage:
你可以用这个struct包来做到这一点:
import struct
def binary(num):
return ''.join(bin(ord(c)).replace('0b', '').rjust(8, '0') for c in struct.pack('!f', num))
That packs it as a network byte-ordered float, and then converts each of the resulting bytes into an 8-bit binary representation and concatenates them out:
将其打包为网络字节顺序浮点数,然后将每个结果字节转换为 8 位二进制表示并将它们连接起来:
>>> binary(1)
'00111111100000000000000000000000'
Edit: There was a request to expand the explanation. I'll expand this using intermediate variables to comment each step.
编辑:有人要求扩大解释。我将使用中间变量来扩展它来评论每个步骤。
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)
And the result for a few examples:
以及一些示例的结果:
>>> 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'
回答by mgilson
Here's an ugly one ...
这是一个丑陋的...
>>> import struct
>>> bin(struct.unpack('!i',struct.pack('!f',1.0))[0])
'0b111111100000000000000000000000'
Basically, I just used the struct module to convert the float to an int ...
基本上,我只是使用 struct 模块将 float 转换为 int ...
Here's a slightly better one using ctypes:
这是一个稍微好一点的使用ctypes:
>>> import ctypes
>>> bin(ctypes.c_uint.from_buffer(ctypes.c_float(1.0)).value)
'0b111111100000000000000000000000'
Basically, I construct a floatand use the same memory location, but I tag it as a c_uint. The c_uint's value is a python integer which you can use the builtin binfunction on.
基本上,我构造 afloat并使用相同的内存位置,但我将其标记为c_uint. 该c_uint的值是一个Python整数,您可以使用内建bin的功能。
回答by TheMeaningfulEngineer
After browsing through lots of similar questions I've written something which hopefully does what I wanted.
在浏览了很多类似的问题后,我写了一些希望能满足我想要的东西。
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:]
binrepis the result.
Each part will be explained.
binrep是结果。将解释每个部分。
f = 1.00
negative = False
if f < 0:
f = f*-1
negative = True
Converts the number to a positive if negative, and sets the variable negative to false. The reason for this is that the difference between positive and negative binary representations is just in the first bit, and this was the simpler way than to figure out what goes wrong when doing the whole process with negative numbers.
如果为负,则将数字转换为正数,并将变量负数设置为 false。这样做的原因是正负二进制表示之间的区别只是在第一位,这是比用负数进行整个过程时找出问题更简单的方法。
s = struct.pack('>f', f) #'?\x80\x00\x00'
p = struct.unpack('>l', s)[0] #1065353216
hex_data = hex(p) #'0x3f800000'
sis a hex representation of the binary f. it is however not in the pretty form i need. Thats where p comes in. It is the int representation of the hex s. And then another conversion to get a pretty hex.
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:]
scaleis the base 16 for the hex. num_of_bitsis 32, as float is 32 bits, it is used later to fill the additional places with 0 to get to 32. Got the code for binrepfrom this question. If the number was negative, just change the first bit.
scale是十六进制的基数 16。num_of_bits是 32,因为浮点数是 32 位,它稍后用于用 0 填充额外的位置以达到 32。binrep从这个问题中得到了代码。如果数字是负数,只需更改第一位。
I know this is ugly, but i didn't find a nice way and I needed it fast. Comments are welcome.
我知道这很丑陋,但我没有找到一个好的方法,我需要它很快。欢迎评论。
回答by Mark Ransom
This problem is more cleanly handled by breaking it into two parts.
通过将其分成两部分,可以更清晰地处理此问题。
The first is to convert the float into an int with the equivalent bit pattern:
第一种是将浮点数转换为具有等效位模式的 int:
def float32_bit_pattern(value):
return sum(ord(b) << 8*i for i,b in enumerate(struct.pack('f', value)))
Next convert the int to a string:
接下来将 int 转换为字符串:
def int_to_binary(value, bits):
return bin(value).replace('0b', '').rjust(bits, '0')
Now combine them:
现在组合它们:
>>> int_to_binary(float32_bit_pattern(1.0), 32)
'00111111100000000000000000000000'
回答by TheMeaningfulEngineer
回答by Robert Hughes
You can use the .format for the easiest representation of bits in my opinion:
在我看来,您可以使用 .format 来最简单地表示位:
my code would look something like:
我的代码看起来像:
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
Output:
输出:
>>> a = 5.0
'01000000101000000000000000000000'
>>> b = 1.0
'00111111100000000000000000000000'
回答by dkhammond
Several of these answers did not work as written with Python 3, or did not give the correct representation for negative floating point numbers. I found the following to work for me (though this gives 64-bit representation which is what I needed)
其中一些答案与 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) )
回答by Eric
For the sake of completeness, you can achieve this with numpy using:
为了完整起见,您可以使用 numpy 来实现这一点:
f = 1.00
int32bits = np.asarray(f, dtype=np.float32).view(np.int32).item() # item() optional
You can then print this, with padding, using the bformat specifier
然后,您可以使用b格式说明符使用填充打印此内容
print('{:032b}'.format(int32bits))
回答by johnml1135
This is a little more than was asked, but it was what I needed when I found this entry. This code will give the mantissa, base and sign of the IEEE 754 32 bit float.
这比要求的要多一点,但是当我找到这个条目时,这是我所需要的。此代码将给出 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)
output:
输出:
bits: 10111111010000000000000000000000
sig (bin): 110000000000000000000000
sig (float): 1.5
base:-1
sign:-1
recreate:-0.75
回答by tttzof351
Convert float between 0..1
在 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) > places:
return answer
b = n * 2
if b > 1:
answer += '1'
n = b - 1
else:
answer += '0'
n = b
return answer

