9

在进行二进制文件写入时,我在 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,)

多余的数字是怎么回事?这是一个舍入错误吗?这是如何运作的?

4

2 回答 2

8

在大多数平台上,Python 浮点数就是 C 所称的 a double,但是您将数据写成 as float,它的精度只有一半。

如果你使用double,你的精度损失会更少:

>>> data = struct.pack('d',value)
>>> struct.unpack('d',data)
(1.23456,)
>>> data = struct.pack('f',value)
>>> struct.unpack('f',data)
(1.2345600128173828,)

floatstruct 格式仅提供单精度(24 位用于显着精度)

于 2013-04-23T09:23:19.040 回答
0

这是一个十进制到二进制的问题。

你知道小数中的一些分数是如何重复的吗?例如,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 意味着你有一个重复的二进制小数,它永远重复。

但你不能永远重复。这意味着您必须将小数四舍五入才能适合编码浮点数的二进制数字。

当您转换回十进制时,会显示舍入误差。

编码的结果是:尽可能晚地计算除法,以防止这些错误随着每次计算而累积。

于 2019-04-05T00:15:54.210 回答