在执行二进制文件写入时,我在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
结构格式仅提供单个精度(24 位表示有效精度(。
十进制到二进制的问题。
你知道十进制中的一些分数是如何重复的吗? 例如,1/3 是 0.3333333-> 永远。1/7 是 0.142857142857[142857]-> 永远。
所以这里是踢球者:重复分数是那些分母的因子不是 10 的分数——例如不是 2 和/或 5 的倍数。
- 1/2 平均分配
- 1/3 次重复
- 1/4 平均分配
- 1/5 平均分配
- 1/6 次重复
- 1/7 次重复
- 1/8 平均分配
- 1/9 次重复
- 1/10 平均分配
- 1/11 重复
- 等等
那么现在它在二进制中是如何工作的呢? 嗯,这有点糟糕,因为唯一平均分配的因素是 2。 除 2 之外的所有其他素数都将具有永远重复的重复小数 - 这包括十分之一、百分之一等,它们的分母中都有一个 5 的因子。 1.2345 是 12345/10000,分母中有因数 2 和 5,5 表示二进制中有一个永远重复的重复小数。
但你不能永远重复。 这意味着您必须四舍五入小数以适合编码浮点数的二进制数字。
转换回十进制时,将显示舍入误差。
编码的结果是:尽可能晚地计算除法,以防止这些错误在每次计算中累积。