[英]Python: create fixed point decimal from two 32-bit ints (one for int portion, one for decimal)
我从具有二进制数据的文件中解压缩了64位时间戳,其中前32位是秒数,而后32位是秒的小数。 我一直坚持如何将底部的32位实际转换为分数,而不是逐位循环。
有什么建议?
仅供参考,编号4ca1f350 9481ef80
翻译为1285682000.580107659
编辑:对于上下文:数据来自数据包捕获设备,我见过的文档说它的小数部分具有大约纳秒精度(特别是它输出32位中的29位,给出~2ns)。
您可以将十六进制数除以最大值以获得正确的比率:
>>> float(0x9481ef80) / 0x100000000
0.58010765910148621
要以足够的精度(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
请注意,浮点数使用“IEEE双格式”,因此它只能保持53位精度:
>>> a = 0x9481ef80 / 2**32 + 0x4ca1f350
>>> b = 0x9481ef90 / 2**32 + 0x4ca1f350
>>> a == b
如果将小数部分存储为自己的变量就可以了,但如果是这种情况,为什么不保持原样呢?
>>> 0x9481ef80 / 2**32
0.5801076591014862
>>> 0x9481ef90 / 2**32
0.5801076628267765
从那时起你没有说秒。 它看起来像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
。 请解释。 “翻译”声明的来源是什么? 你还有其他的例子吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.