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

2 views (last 30 days)
Kyohei Fujimoto
Kyohei Fujimoto on 3 Jun 2021
Commented: Kyohei Fujimoto on 3 Jun 2021
下記のような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 Yoshino
Hiro Yoshino 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.

Categories

Find more on Data Type Conversion in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!