我从具有二进制数据的文件中解压缩了64位时间戳,其中前32位是秒数,而后32位是秒的小数。我一直坚持如何将底部的32位实际转换为分数,而不是逐位循环。
有什么建议吗?
作为参考,数字4ca1f350 9481ef80
会转换为1285682000.580107659
编辑: 对于上下文:数据来自数据包捕获设备,我见过的文档说它的小数部分具有大约纳秒精度(特别是它输出32位中的29位,给出~2ns)。
答案 0 :(得分:3)
您可以将十六进制数除以最大值以获得正确的比率:
>>> float(0x9481ef80) / 0x100000000
0.58010765910148621
答案 1 :(得分:2)
要以足够的精度(32 + 29 = 61位)表示积分和小数部分之和,需要一个十进制(默认为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
请注意,float使用“IEEE双格式”,因此它只能保持53位精度:
>>> a = 0x9481ef80 / 2**32 + 0x4ca1f350
>>> b = 0x9481ef90 / 2**32 + 0x4ca1f350
>>> a == b
如果将小数部分存储为自己的变量,那就没关系了,但是如果是这样的话,为什么不将它保持原样呢?
>>> 0x9481ef80 / 2**32
0.5801076591014862
>>> 0x9481ef90 / 2**32
0.5801076628267765
答案 2 :(得分:1)
自以来,您没有说秒。它看起来像1970-01-01。您可以计算一个软糖因子,它是纪元(1970-01-01)与您预期的最低值之间的秒数。然后调整每个值... vadj = float(hi32 - fudge) + lo32 / 2.0 ** 32
如果max(hi32)和min(lo32)之间的差值小于约6天(应该足够进行数据包捕获练习(?)),那么你只需要19位的hi32 - fudge。 19位+ 32位是51位 - 在Python float 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
。请解释。 “翻译”声明的来源是什么?你还有其他的例子吗?