3

バイナリ データを含むファイルからアンパックされた 64 ビットのタイムスタンプがあります。上位 32 ビットは秒数で、下位 32 ビットは秒の端数です。ビットごとにループせずに、下位32ビットを実際に分数に変換する方法にこだわっています。

助言がありますか?

参考までに、数字は次の4ca1f350 9481ef80ように変換されます。1285682000.580107659

編集:コンテキストについて:データはパケットキャプチャデバイスから取得され、私が見たドキュメントによると、小数部分はおよそナノ秒の精度です(具体的には、32ビットのうち29ビットを出力し、〜2nsを与えます)。

4

3 に答える 3

3

16進数を可能な最大値で割ると、正しい比率が得られます。

>>> float(0x9481ef80) / 0x100000000
0.58010765910148621
于 2010-09-28T14:52:17.517 に答える
2

整数部分と小数部分の合計を十分な精度(32 + 29 = 61ビット)で表すには、10進数(デフォルトでは10進数の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は「IEEEdoubleformat」を使用するため、53ビットの精度しか保持できないことに注意してください。

>>> a = 0x9481ef80 / 2**32 + 0x4ca1f350
>>> b = 0x9481ef90 / 2**32 + 0x4ca1f350
>>> a == b

小数部分を独自の変数として格納することは問題ありませんが、その場合は、そのままにしておくのはどうでしょうか。

>>> 0x9481ef80 / 2**32
0.5801076591014862
>>> 0x9481ef90 / 2**32
0.5801076628267765
于 2010-09-28T14:53:25.823 に答える
1

いつから何秒も言いませんでした。1970-01-01 以降のようです。エポック (1970-01-01) と予想される最低値の間の秒数であるファッジ ファクターを計算できます。次に、各値を調整します...vadj = float(hi32 - fudge) + lo32 / 2.0 ** 32

max(hi32) と min(lo32) の差が約 6 日分未満の場合 (パケット キャプチャの演習 (?​​) には十分なはずです)、hi32 - fudge には 19 ビットしか必要ありません。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) が本当に必要ですか? IMHO、float(difference(ts1, ts2))代わりにを実行すれば、問題float(ts1) - float(ts2)ありません。

編集 3:あいまいさ/矛盾の警告

質問を編集して、次の問題に対処してください。

あなたはコメントで、「」「私が見ているドキュメントでは、小数部分がナノ秒の精度を持っていると言っています(具体的には、32ビットのうち29ビットを出力します)」」と言っています。そのドキュメントの URL を提供してください。

1 秒は 1000000000 ( 10**9) ナノ秒です。小数部分にはmath.log(10**9, 2)、29 ビットではなく、切り上げ (つまり、29.897352853986263 の切り上げ、つまり 30) ビットが必要であると予想されます。説明してください。

答えてください: 利用可能な 32 ビットのうち、29 ビットと 30 ビットのどちらが小数部を含み、3 ビットと 2 ビットのどちらが常にゼロですか?

次に、 で割ることによってナノ秒を秒に変換することが期待され10**9ます。ただし、あなたの質問のステートメント """the number 4ca1f350 9481ef80 translates to 1285682000.580107659""" は で割ることと一致してい2**32ます。実際、0x9481ef80 は 2,491,543,424 で、2 倍以上です10**9。説明してください。「に翻訳する」ステートメントのソースは何ですか? 他に例はありますか?

于 2010-09-29T12:59:18.587 に答える