2012-03-16 24 views
1

浮動小数点エラーでPythonを使用して問題が発生しました。私はここでそれを言及することは有益かもしれませんが。Python浮動小数点エラー

私は5000Hzでデータを記録する外部サンプリングシステムを持っています。タイムスタンプを取得するために、私は最初の時間をとり、連続するサンプルのタイムスタンプを取得するために(1.0/5000)を追加します。私は非常に迅速に現在の時間(time.time())は、ループを使用して計算された時間から漂って気づいた。単純な計算を行うと、目立っドリフトがあった - いくつかのコード:

start_time = time.time() 
start_time_test = start_time 
#get 512 samples - takes 512*1.0/5000 seconds 
for i in arange(512): 
    start_time = start_time + (1.0/5000) #5khz 

start_time_test = start_time_test + 512*(1.0/5000) 
print time.time() - start_time_test #no drift 
print time.time() - start_time # drifts 
print start_time_test - start_time # constant increment 

は今start_time_testとstart_timeの間の差は無視できないではない - それは1.69e-5 512のブロックごとに非常に迅速に追加することを開始についてです。私はすぐに浮動小数点のエラーがここに再生に来て驚いている。ここで小数点以下のpacakgeの使用を調べて、エラーを制限するつもりです。

浮動小数点エラーのこのレベルは予想されますか? - 私が何かばかげたことをする可能性があり、浮動小数点エラーではないことを忘れないでください。

+1

ここに質問はありません。 –

+0

罰金 - このレベルのドリフトは予想されますか? –

+0

[浮動小数点精度の問題](http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems)は、太陽の下では何も新しいものではありません。[decimal library](http://docs.python.org /library/decimal.html) – Aprillion

答えて

4
a=time.time() 
(a+1/5000.0)-a 
#0.00020003318786621094 
1/5000.0 
#0.0002 
1331918373+1/5000.0-1331918373 
#0.00020003318786621094 

時間フロートは1/5000よりも道も大きいので、あなたが^ -4 10^9 + 2を追加したとき、2^-4部分が精度を失い。

+0

私はここで、UNIXの時間と小さなインクリメントの間の値の大きな違いが問題であることを確認しました。完璧な意味合いを持つ。私はまだ測定の絶対時間を持ちたいと思いますが、デシマルパッケージが役立つかどうかを調べることに興味がありますが、日時はより適切かもしれません。 –

+1

@Rossあなたの最善の策は、絶対値ではなく相対値で作業することです値。 –

+0

datetimeとtimedeltaを使用するとうまくいきます:start_time = datetime.utcnow()t_del = timedelta(microseconds = 200)そしてループ内でstart_time = start_time + d_delを実行します。 –

0

1.0/5000.0は、終了バイナリ表現を持たない。同じ実験を1.0/4096.0で実行すると、差がゼロになります。しかし、あなたのテストでは、各プリントでtime.time()を呼び出し、time.time()は毎回異なる結果を生成します。あなたが分母の選択に伴う数値的な問題を見たい場合は、time.time()を画像から外してください。私は8.743e-16あなたの例の累積的なエラーを得る。

time.time()についての大きな点は大きな数であり、したがって小さな数値を追加することで精度が失われることは、正しい一般的な観察です。しかし、私はそれがこの場合の犯人だとは思わない。追加、4096.0:

DT:5000.0、追加:これは、結果を生成

import time 
for dt in [5000.0, 2096.0]: 
    start = time.time() 
    add = start 
    for i in range(512): 
     add += 1.0/dt 
    mult = start + 512.0/dt 
    diff = abs(add - mult) 
print "dt:%s, add:%s, mult:%s, diff:%s" % (dt, add, mult, diff) 

:1332070890.23 MULT:1332070890.23、差分:1.69277191162e-05

DT以下のコードを検討1332070890.25をMULT:1332070890.25、デフ:0.0

+0

これは、 'start_time'が0に初期化されている場合にのみ当てはまります。そうでない場合、答えはfalseです。そして、私は 'start_time'を0に初期化することはできないと信じています。エラーの重要性は' start_time'の初期値に対して非常に敏感です。 –

0

小さな番号に大きな数字を追加することがこの場合の原因であるかどうかをテストしました。答えは「いいえ」です。倍精度は十分な有効桁数を持つので、オフセットは必要ありません。

数値直角で知られており、「本当の作っリアルタイムコンピューティング」の145ページに記載されている一般的なブービートラップである理由フォアマンS.アクトンから

は何が起こるかというと、このです:最初の近似は良好です。あなたは3.3E-8の非常に小さな誤差を得ます。しかし、あなたはエラーを合計しています:

エラー2は6.6E-8です。

エラー3は2E-7

エラー30は1E-6

エラー300である1E-7

エラー6である1E-5

エラー512が1です。6927719116210938E-5

最高の精度でタイムスタンプを計算するための正しい方法:

for i in arange(512): 
time_stamp = time_stamp_start + i/5000.0; 

また、代わりに継続的に成長しているエラーの実際と計算値の違いはランダムのような違いを持っ​​ている利点を持っていますキャンセルしてください。

関連する問題