python3如何将字节转换为浮点?

python3如何将字节转换为浮点?,python,Python,我想详细了解python如何将字节转换为浮点。 让我们创建一个仅包含一个float 23.0的二进制文件: ~> echo 23 > 23.a ~> a2b < 23.a n1=1 > 23.b 所以,我想知道python是如何将字节“\x00\x00\xb8A”转换为float 23.0的?这与DEC-BIN-HEX-ASCII表示法有关,但我在试图理解这一点时已经伤了脑筋 DEC = 23 BIN = 0000 0000 0001 0111 HEX

我想详细了解python如何将字节转换为浮点。
让我们创建一个仅包含一个float 23.0的二进制文件:

~> echo 23 > 23.a  
~> a2b < 23.a n1=1 > 23.b
所以,我想知道python是如何将字节“\x00\x00\xb8A”转换为float 23.0的?这与DEC-BIN-HEX-ASCII表示法有关,但我在试图理解这一点时已经伤了脑筋

DEC = 23  
BIN = 0000 0000 0001 0111  
HEX =    0    0    1    7
我们如何从中获得“\x00\x00\xb8A”?反之亦然,“\x00\x00\xb8A”如何转换为23.0?
谁能一步一步地给我解释一下吗?谢谢。

这显然是:

对于
'f'
'd'
转换代码,压缩表示使用IEEE 754 binary32(对于
'f'
)或binary64(对于
'd'
)格式,而不考虑平台使用的浮点格式

因此,要理解该格式,请参考;您使用了
f
代码,因此请查找

此格式由32位组成,分为:

  • 符号位:1位
  • 指数宽度:8位
  • 有效位精度:24位(显式存储23位)
将二进制数据视为位(您将其视为小尾端,因此我将其反转以匹配Wikipedia的大尾端排序):

我们看到符号是0,指数宽度是131(在2的补码中,因此负127等于4),有效位精度或尾数是1.4375(1+1/4+1/8+1/16,每个二进制分数是一个启用位)

这些值一起构成实际的浮点值:

>>> 1 * 2 ** 4 * 1.4375 (sign, positive, times 2 to the power exponent, times fractions)
23.0

换一种方式,用二进制表示整数和小数点后的值;您可能需要近似非整数部分,因为二进制分数不能表示所有可能的实数。23.0没有非整数组件,因此在这里很容易,我们只需将整数组件转换为二进制:

>>> format(23, 'b')
'10111'
所以实数的二进制表示是
10111.0
。然后将小数点上移或下移,得到
1
和一个分数;在这里,您需要将小数点向上移动4个点到
1.0111
。这将给出指数(4)和有效值(0111加上未使用分数的另外19个零)。该值为正数,因此将符号编码为
0
,将指数编码为有符号值(将127==131,将131编码为二进制==
1000011
),并添加有效值:

0 10000011 01110000000000000000000
将其切分为4组8位(4字节),得到
0x41 0xB8 0x00 0x00
。Python的
repr()
字节输出尽可能为字节提供可打印的ASCII字符,
0x41
是ASCII表中的字母
a

>>> bytes([0b01000001, 0b10111000, 0b00000000, 0b00000000])
b'A\xb8\x00\x00'
反转这些字节以获得一个小的endian表示:

>>> bytes([0b01000001, 0b10111000, 0b00000000, 0b00000000])[::-1]
b'\x00\x00\xb8A'

您可以可视化IEEE binary32格式如何使用。

这显然是:

对于
'f'
'd'
转换代码,压缩表示使用IEEE 754 binary32(对于
'f'
)或binary64(对于
'd'
)格式,而不考虑平台使用的浮点格式

因此,要理解该格式,请参考;您使用了
f
代码,因此请查找

此格式由32位组成,分为:

  • 符号位:1位
  • 指数宽度:8位
  • 有效位精度:24位(显式存储23位)
将二进制数据视为位(您将其视为小尾端,因此我将其反转以匹配Wikipedia的大尾端排序):

我们看到符号是0,指数宽度是131(在2的补码中,因此负127等于4),有效位精度或尾数是1.4375(1+1/4+1/8+1/16,每个二进制分数是一个启用位)

这些值一起构成实际的浮点值:

>>> 1 * 2 ** 4 * 1.4375 (sign, positive, times 2 to the power exponent, times fractions)
23.0

换一种方式,用二进制表示整数和小数点后的值;您可能需要近似非整数部分,因为二进制分数不能表示所有可能的实数。23.0没有非整数组件,因此在这里很容易,我们只需将整数组件转换为二进制:

>>> format(23, 'b')
'10111'
所以实数的二进制表示是
10111.0
。然后将小数点上移或下移,得到
1
和一个分数;在这里,您需要将小数点向上移动4个点到
1.0111
。这将给出指数(4)和有效值(0111加上未使用分数的另外19个零)。该值为正数,因此将符号编码为
0
,将指数编码为有符号值(将127==131,将131编码为二进制==
1000011
),并添加有效值:

0 10000011 01110000000000000000000
将其切分为4组8位(4字节),得到
0x41 0xB8 0x00 0x00
。Python的
repr()
字节输出尽可能为字节提供可打印的ASCII字符,
0x41
是ASCII表中的字母
a

>>> bytes([0b01000001, 0b10111000, 0b00000000, 0b00000000])
b'A\xb8\x00\x00'
反转这些字节以获得一个小的endian表示:

>>> bytes([0b01000001, 0b10111000, 0b00000000, 0b00000000])[::-1]
b'\x00\x00\xb8A'


您可以可视化IEEE binary32格式的工作方式。

a2b命令的作用是什么?我的Debian、CentOS或OS X系统都没有这个命令。@Martijn你说得对,我忽略了这一点。这是“地震Unix”的一部分。逐行读取ascii浮点并将其转换为二进制。我相信,在这种情况下,小恩迪安。对,那么就是这样了吗?a2b命令是做什么的?我的Debian、CentOS或OS X系统都没有这个命令。@Martijn你说得对,我忽略了这一点。这是“地震Unix”的一部分。逐行读取ascii浮点并将其转换为二进制。小恩迪安,我相信,在这种情况下。对,那么就这样了?好的,谢谢。现在很清楚如何将32二进制转换为IEEE浮点。但我仍然不知道,我们是如何从b'\x00\x00\xb8A'和23'中得到'0100000111000000000000000000'的。@Michael:
b'\x00\x00\xb8A
表示4个字节,值0,0,1