3

我从包含二进制数据的文件中解压缩了一个 64 位时间戳,其中前 32 位是秒数,后 32 位是秒的分数。我坚持如何将底部的 32 位实际转换为分数,而不是逐位循环。

有什么建议么?

作为参考,数字4ca1f350 9481ef80转换为1285682000.580107659

编辑:对于上下文:数据来自数据包捕获设备,我看到的文档说它的小数部分具有大约纳秒的精度(特别是它输出 32 位中的 29 位,大约 2ns)。

4

3 回答 3

3

您可以将十六进制数除以可能的最大值以获得正确的比率:

>>> float(0x9481ef80) / 0x100000000
0.58010765910148621
于 2010-09-28T14:52:17.517 回答
2

要以足够的精度(32 + 29 = 61 位)表示整数和小数部分的总和,您需要一个 Decimal(默认为 28 个十进制数字,对于 93 位足够),

>>> from decimal import Decimal
>>> Decimal(0x9481ef80) / Decimal(2**32) + Decimal(0x4ca1f350)
Decimal('1285682000.580107659101486206')

或分数(精确),

>>> from fractions import Fraction
>>> Fraction(0x9481ef80, 2**32) + Fraction(0x4ca1f350)
Fraction(43140329262089183, 33554432)
>>> float(_)
1285682000.5801077

请注意,浮点数使用“IEEE 双格式”,因此它只能保存 53 位精度:

>>> a = 0x9481ef80 / 2**32 + 0x4ca1f350
>>> b = 0x9481ef90 / 2**32 + 0x4ca1f350
>>> a == b

如果您将小数部分存储为自己的变量,那很好,但如果是这种情况,为什么不保持原样呢?

>>> 0x9481ef80 / 2**32
0.5801076591014862
>>> 0x9481ef90 / 2**32
0.5801076628267765
于 2010-09-28T14:53:25.823 回答
1

你没有说几秒从什么时候开始。好像是从 1970-01-01 开始的。您可以计算一个 fudge 因子,它是 epoch (1970-01-01) 和您预期的最低值之间的秒数。然后你调整每个值......vadj = float(hi32 - fudge) + lo32 / 2.0 ** 32

如果 max(hi32) 和 min(lo32) 之间的差异小于大约 6 天(对于数据包捕获练习 (?) 应该足够了),那么 hi32 - fudge 只需要 19 位。19 位 + 32 位是 51 位——在 Python 浮点 IIRC 的精度范围内。

这里已经很晚了,所以我不打算做详细的分析,但上面应该给你的图片。

编辑:为什么@unwind 的回答不起作用:

>>> a = 0x00000001/4294967296.0 + 0x4ca1f350
>>> b = 0x00000002/4294967296.0 + 0x4ca1f350
>>> b - a
0.0
>>>

编辑 2:除了 str()、repr()、timestamp_from_str() 之外,您还想对时间戳执行哪些操作?差异是关于所有想到的。你可以使用这样的东西:

>>> class TS64(object):
...   def __init__(self, hi, lo):
...     self.hi = hi
...     self.lo = lo
...   def float_delta(self, other):
...     hi_delta = self.hi - other.hi
...     # check that abs(hi_delta) is not too large, if you must
...     return hi_delta + (self.lo - other.lo) / 4294967296.0
...
>>> a = TS64(0x4ca1f350, 1)
>>> b = TS64(0x4ca1f350, 2)
>>> b.float_delta(a)
2.3283064365386963e-10
>>> repr(_)
'2.3283064365386963e-10'
>>>

关于我的“如果你必须”评论:如果观察间隔超过 6 天,你真的需要精确到最后(秒 / 2 ** 32)吗?恕我直言,如果你不这样做float(difference(ts1, ts2))float(ts1) - float(ts2)你应该没问题。

编辑 3:歧义/不一致警报

请编辑您的问题以解决以下问题:

您在评论中说“”“我正在查看的文档说它的小数部分具有纳秒精度(特别是它输出 32 位中的 29 位)”“”。请提供该文档的 URL。

一秒钟有 1000000000 ( 10**9) 纳秒。人们会期望小数部分需要math.log(10**9, 2)四舍五入(即 29.897352853986263 向上舍入,即 30)位,而不是 29。请解释。

请回答:在可用的 32 位中,哪些 29 位或 30 位包含小数部分,哪些 3 位或 2 位始终为零?

其次,人们希望通过除以将纳秒转换为秒10**9。但是,您在问题中的陈述 """ 数字 4ca1f350 9481ef80 转换为 1285682000.580107659""" 与除以 一致2**32。事实上 0x9481ef80 是 2,491,543,424 大于两倍10**9。请解释。“翻译为”语句的来源是什么?你还有其他例子吗?

于 2010-09-29T12:59:18.587 回答