1. ホーム
  2. matlab

[解決済み] MATLABでマシンイプシロンを計算する方法は?

2022-02-12 15:52:30

質問内容

機械εを求める必要があり、以下のようにしています。

eps = 1;

while 1.0 + eps > 1.0 do
    eps = eps /2;
end

ところが、こんな風に表示されるんです。

Undefined function or variable 'do'. 
Error in epsilon (line 3) 
while 1.0 + eps > 1.0 do

どうすればいいのでしょうか?

解決方法は?

まず、何よりも大切なことは do キーワードはコードから削除してください。 また eps を実際の変数として使用します。 これはMATLABであらかじめ定義された関数で、以下の計算を行います。 マシンイプシロン を計算しようとしているのです。 という変数を作ることで eps そのため、この関数を必要とするMATLABの他の関数が予期せぬ動作をすることになり、それはあなたが望むことではありません。

代わりに何か別のものを使ってください。 macheps . また、アルゴリズムが少し間違っています。 をチェックする必要があります。 1.0 + (macheps/2) の中に while ループではなく 1.0 + macheps .

つまり、こうするのです。

macheps = 1;

while 1.0 + (macheps/2) > 1.0
    macheps = macheps / 2;
end

これは、次のようになります。 2.22 x 10^{-16} と入力すると、MATLAB と一致します。 eps をコマンドプロンプトで表示します。 再確認のため。

>> format long
>> macheps

macheps =

     2.220446049250313e-16

>> eps

ans =

     2.220446049250313e-16


ボーナス

ご存じないかもしれませんが、マシンイプシロンとは、浮動小数点演算による相対誤差の上限を示すものです。 言い換えれば、浮動小数点数を格納するために使用されるビット数が有限であるため、真の浮動小数点数とコンピュータで計算されたものとの間に予想される最大の差になります。

思い起こせば、浮動小数点数はどうしてもコンピュータ(あるいはかなりのデジタル機器)では2進数のビットで表現される。 という点では IEEE754浮動小数点規格 MATLABは、すべての数値が以下のような型であると仮定しています。 double これは浮動小数点数を64ビットで表します。 明示的に別の型にキャストすることで、この動作をオーバーライドできることは明らかです。 IEEE 754 浮動小数点規格では double の精度を表す52ビットがあります。 分数 の部分は、数値の一部です。

ここで、私が言っていることを分かりやすく図にしてみました。

出典 ウィキペディア

符号用に1ビット、指数基底用に11ビット、そして最後に分数部用に52ビットが確保されているのがわかる。 これを合計すると64ビットになる。分数部は2を底とし、-1から-52までの負の指数を持つ数値の集合または総和である。 浮動小数点数のMSBは次のように始まります。 2^{-1} まで、すべて 2^{-52} をLSBとする。 基本的に、マシンイプシロンは、2つの数値が以下のようなものであると仮定して、2進数で1ビット増加した場合の最大解像度差を計算します。 同じ 記号と 同じ 指数基底 技術的に言えば、マシン・イプシロンが実際に等しいのは 2^{-52} というのは、先ほどお話したような条件がある場合、浮動小数点の1ビットの分解能はこれが最大だからです。

実際に上のコードをよく見てみると、2による除算は ビットシフト を1回繰り返すごとに1つずつ右へ移動し、全数1、つまり 2^{0} そして、この数値を取り、これを1に加えます。 このビットシフトした値に1を足した値が何になるかを見ながらビットシフトを続け、右にビットシフトしたときに変化がなくなるところまで行きます。 これ以上右へビットシフトすると、値は次のようになります。 0 アンダーフローによるものであるため 1.0 + 0.0 = 1.0 であり、これはもはや > 1.0 というもので、これは while ループがチェックしています。

一度 while ループが終了すると、この閾値がマシンイプシロンを定義することになります。 もし興味があるなら、もしあなたが 2^{-52} をコマンドプロンプトで実行すると、次のようになります。 eps が等しい。

>> 2^-52

ans =

     2.220446049250313e-16

これは、1ビットを52回右にシフトしているので、ループが停止する前のポイントはLSBであり、次のようになります。 2^{-52} . 念のため、もしカウンターを while ループの中で、何回 while を実行すると、ちょうど52回実行されることになり、これは52ビット右シフトすることを意味します。

macheps = 1;
count = 0;
while 1.0 + (macheps/2) > 1.0
    macheps = macheps / 2;
    count = count + 1;
end

>> count

count =

  52