繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM