Python:从两个 32 位整数创建定点小数(一个用于整数部分,一个用于十进制)
我有一个从二进制数据文件中解压出来的 64 位时间戳,其中前 32 位是秒数,后 32 位是秒的小数部分。我一直困惑于如何将底部 32 位实际转换为分数,而不需要逐位循环它。
有什么建议吗?
作为参考,数字 4ca1f350 9481ef80
转换为 1285682000.580107659
编辑: 对于上下文:数据来自数据包捕获设备,我看到的文档说小数部分的精度大约为纳秒(具体来说,它输出 32 位中的 29 位,给出约 2ns)。
I have a 64-bit timestamp unpacked from a file with binary data, where the top 32 bits are the number of seconds and the bottom 32 bits are the fraction of the second. I'm stuck with how to actually convert the bottom 32 bits into a fraction without looping through it bit-by-bit.
Any suggestions?
For reference, the number 4ca1f350 9481ef80
translates to 1285682000.580107659
Edit:
For context: the data comes from a packet capture device and the documentation I've seen says that it the fractional part has roughly nano-second precision (specifically it outputs 29 of the 32 bits, giving ~2ns).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您只需将十六进制数除以可能的最大值即可得到正确的比率:
You can just divide the hex number by the maximum possible to get the correct ratio:
为了以足够的精度(32 + 29 = 61 位)表示整数部分和小数部分的总和,您需要一个 Decimal(默认 28 位小数,足以 93 位),
或 Fraction(精确),
请注意,浮点数使用“IEEE 双精度格式”,因此它只能保存 53 位精度:
如果将小数部分存储为自己的变量就可以了,但如果是这样,为什么不保持原样呢?
To represent the sum of integral and fractional part with enough precision (32 + 29 = 61 bits), you need a Decimal (28 decimal digits by default, which is enough for 93 bits),
or Fraction (exact),
Note that a float uses "IEEE double format" so it can only hold 53 bits of precision:
It is fine if you store the fractional part as its own variable, but if that's the case, why not just keep it as-is?
你没有说从什么时候开始的秒数。看起来是从 1970 年 1 月 1 日开始的。您可以计算一个模糊因子,即纪元 (1970-01-01) 与您预期的最低值之间的秒数。然后调整每个值...
vadj = float(hi32 - fudge) + lo32 / 2.0 ** 32
如果 max(hi32) 和 min(lo32) 之间的差异小于大约 6 天的值(对于数据包捕获练习来说应该足够了(?)),那么 hi32 只需要 19 位 - 软糖。 19 位 + 32 位等于 51 位——在 Python 浮点 IIRC 的精度范围内。
现在已经很晚了,所以我不打算进行详细分析,但上面的内容应该可以让您了解情况。
编辑:为什么@unwind的答案不起作用:
编辑2:除了str()、repr()、timestamp_from_str()之外,您还想对时间戳执行哪些操作?差异就是想到的一切。你可以使用这样的东西:
关于我的“如果你必须”评论:如果观察结果相隔超过 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
的两倍。请解释一下。 “翻译成”声明的来源是什么?你还有其他例子吗?You didn't say seconds since when. It looks like it's since 1970-01-01. You can calculate a fudge factor that is the number of seconds between the epoch (1970-01-01) and your expected lowest value. Then you adjust each value ...
vadj = float(hi32 - fudge) + lo32 / 2.0 ** 32
If the difference between max(hi32) and min(lo32) is less than about 6 days worth (should be enough for a packet capture exercise (?)), then you need only 19 bits for hi32 - fudge. 19 bits + 32 bits is 51 bits -- within the precision of a Python float IIRC.
It's late here so I'm not going to do a detailed analysis but the above should give you the picture.
Edit: why @unwind's answer doesn't work:
Edit 2: What operations do you want to do on a timestamp apart from str(), repr(), timestamp_from_str()? Difference is about all that comes to mind. You can use something like this:
About my "if you must" comment: If the observations are more than 6 days apart, do you really need accuracy down to the last (second / 2 ** 32)??? IMHO, if you do
float(difference(ts1, ts2))
instead offloat(ts1) - float(ts2)
, you should be OK.Edit 3: Ambiguity/inconsistency alert
Please edit your question to address the following issues:
You say in a comment that """the documentation I'm looking at says that it the fractional part has nano-second precision (specifically it outputs 29 of the 32 bits)""". Please provide a URL for that documentation.
There are 1000000000 (
10**9
) nanoseconds in a second. One would expect the fractional part to requiremath.log(10**9, 2)
rounded up (i.e. 29.897352853986263 rounded up i.e. 30) bits, not 29. Please explain.Please answer: Of the 32 bits available, which 29 or 30 bits contain the fractional part and which 3 or 2 bits are always zero?
Secondly one would expect to convert the nanoseconds to seconds by dividing by
10**9
. However your statement in your question """the number 4ca1f350 9481ef80 translates to 1285682000.580107659""" is consistent with dividing by2**32
. In fact 0x9481ef80 is 2,491,543,424 which is greater than twice10**9
. Please explain. What is the source of the "translates to" statement? Do you have any other examples?