Python:从两个32位整数创建定点十进制(一个用于int部分,一个用于十进制)

时间:2010-09-28 14:48:18

标签: python fixed-point

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

有什么建议吗?

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

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

3 个答案:

答案 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。请解释。 “翻译”声明的来源是什么?你还有其他的例子吗?