MATLAB Answers

二つのdatetim​e時刻をコンマ7桁単​位で取得した時の関数​での相違点

2 views (last 30 days)
下記のようなdatetimeを設定し、時刻差を二通りの関数で取得しました
%年、月、日またぎの確認
TIME1=datetime(2017,1,1,0,0,0.0001000);
TIME2=datetime(2016,12,31,23,59,59.9999000);
%計算①
S1=posixtime(TIME1)-posixtime(TIME2);
S11=round(S1*(double(10000000)));
%計算②
S2=seconds(TIME1- TIME2);
S22=round(S2*(double(10000000)));
上記のコードの場合、計算①と②がそれぞれ下記のような結果となりました
--------------------------------------------------------
計算① S1= 2.002716e-04
0.1μsでの表示(7桁でまるめこみ)
計算① S11= 2003
--------------------------------------------------------
計算② S2= 2.000000e-04
0.1μsでの表示(7桁でまるめこみ)
計算② S22= 2000
なぜこのような結果になったのか、わかる方がいれば教えていただければと思います。
MATLABはR2020bを使用しています。
よろしくお願いいたします。

Accepted Answer

Atsushi Ueno
Atsushi Ueno on 3 Jun 2021
Edited: Atsushi Ueno on 3 Jun 2021
>なぜこのような結果になったのか
誤差 - Wikipedia ->浮動小数点数間の減算において桁落ちが発生している為です。
一つの変数内で年,月,日,時,分,秒も計算する必要が有る方法と無い方法の2通りで差分0.0002秒を得ようとしている為です。
>> posixtime(TIME1)
ans = 1.483228800000100e+09
>> posixtime(TIME2)
ans = 1.483228799999900e+09
>> posixtime(TIME1)-posixtime(TIME2)
ans = 2.002716064453125e-04
こちら側は、double型に年月日時分秒を含めた時刻の差を演算しています。0.0002秒の差分の「上側」に13桁もの情報が乗っていて、「下側」の計算に掛けられる有効桁数が少ないのです。double型の仮数部は 52 ビット、自由に動かせる10進の有効桁数は15桁です。その内13桁も「上側」の計算に取られ、「下側」の計算に使える有効桁数はわずか2桁です。それでも浮動小数点数の演算をすると、有効数字桁未満は意味のない(2進数で示せる)結果が出力されます。詳細は:浮動小数点数 - Wikipedia
>> TIME1.Second
ans = 1.000000000000000e-04
>> TIME2.Second
ans = 59.999899999999997
>> TIME1.Second-(TIME2.Second-60)
ans = 2.000000000033197e-04
こちら側は、double型に秒のみを含めた時刻の差を演算しています。TIME1とTIME2はdatetime型というクラスのオブジェクトで、内部に年月日時分秒のプロパティ値を持っています。TIME1-TIME2を演算するとこの内部プロパティ値間の演算が行われる為、seconds関数経由で秒同士の演算結果が得られます。こちらは十分な有効桁数があります。
TIME1=datetime(1970,1,1,0,0,0.0002000);
TIME2=datetime(1970,1,1,0,0,0.0001000);
試しに上記の差分を2通りの方法で計算してみると、質問で問われているような桁落ちが発生しない事を確認しました。上記説明の通り、秒の上に乗っかる年月日時分の数値がゼロになり、秒の差分演算に十分な有効桁数を使える為です。
  1 Comment
Kyohei Fujimoto
Kyohei Fujimoto on 3 Jun 2021
Uenoさま
早速のご回答ありがとうございます。
精度の問題かなと感じていましたが、ここまでの影響があるとは思ってませんでした。
有効桁が15桁など新たな知見も得ることができ、無事納得することができました。
ありがとうございました!!

Sign in to comment.

More Answers (1)

Hiro
Hiro on 3 Jun 2021
コンピュータの中は2進数なので、表現できる数字とそうで無い数字があります。
表現不可能な場合は近似するわけですが、MATLABの標準の double 型は 8byte のメモリを必要とします。従って、数値を近似した際に、浮動小数点の仮数部に使うことができるbitサイズが大きいほど正確に近似できます。
つまり 52 bit が仮数部に用いられるわけですが、答えが同じになるべき計算でも、使っているbit によって答えが変わります。
a =(100000000000000+ 4/3) - (100000000000000+ 1)
a = 0.3281
b = 4/3 - 1
b = 0.3333
a == b
ans = logical
0
a と b は答えが一緒になるはずですが、4/3 の近似の良さが a, b で異なるため、答えが変わってきます。
上のコードでは、差分が同じになるはずですが、基準となる原点を posixtime は大幅にずらしており、それにより数値が大きくなっています。つまり近似の精度が下がっている状態だと考えられます。これが理由です。
  1 Comment
Kyohei Fujimoto
Kyohei Fujimoto on 3 Jun 2021
Hiroさま
近似の精度問題ということで無事納得できました。
これからは桁数も意識して確認してみようと思います。
ありがとうございました!!

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!