在进行二进制文件写入时,我在python中打包和解包二进制浮点数时遇到了一些麻烦。这是我做的:
import struct
f = open('file.bin', 'wb')
value = 1.23456
data = struct.pack('f',value)
f.write(data)
f.close()
f = open('file.bin', 'rb')
print struct.unpack('f',f.read(4))
f.close()
我得到的结果如下:
(1.2345600128173828,)
附加数字是怎么回事?这是一个舍入误差吗?这是如何运作的?
在大多数平台上,Python浮点数是C所谓的double
,但是您将数据写成float
而不是精度的一半。
如果你使用double
,你的精确度损失会更少:
>>> data = struct.pack('d',value)
>>> struct.unpack('d',data)
(1.23456,)
>>> data = struct.pack('f',value)
>>> struct.unpack('f',data)
(1.2345600128173828,)
float
结构格式仅提供single precision (24 bits for the significant precision)。
这是一个十进制到二进制的问题。
你知道十进制中的一些分数是如何重复的吗?例如,1/3是0.3333333->永远。 1/7是0.142857142857 [142857] - >永远。
所以这里是踢球者:重复分数是具有分数的分数,其分数不是10的因子 - 例如不是2和/或5的倍数。
那么现在二进制如何工作?好吧,它有点糟糕,因为唯一分配的因素是2.除了2之外的所有其他素数将具有重复的小数,它们将永远重复 - 包括十分之一,百分之一等,它们在分母中都有一个因子5 。 1.2345是12345/10000,它在分母中有因子2和5,而5意味着你有一个二进制的重复小数,它永远重复。
但你不能永远重复。这意味着您必须舍入小数,以使其适合编码浮点数的二进制数字。
当您转换回十进制时,将显示舍入错误。
编码的结果是:尽可能晚地计算划分,以防止这些错误在每次计算时累积。