2012-01-22 5 views
6

私は二倍の配列を平等のスカラー倍と比較しようとしていますが、特定の状況では平等は決して認識されません。私はこれが二重表現の方法(例えば1.0対1.0)と関係があると考えていますが、私はそれを理解することはできません。 Iが10.2(または10.2000)に等しいかどうかをテストする場合例えばmatlab double comparison

、私は二重の値の数千からなるアレイを生成し、最後の数は、そのうちのいくつかの瞬間に時間的に

10.6000 
-11.0000 
10.2000 
22.6000 
3.4000 

によって与えられます。コマンドarray==10.2(またはarray=10.2000)によって、0の配列を返します。表示された値を手動で配列に配置すると(例:array=[10.6000 -11.0000 10.2000 22.6000 3.4000])、コマンドは成功します(array==10.20 0 1 0 0を返します)。誰かが、値を手動で入力すると、等価性が成功する理由を説明してください。ただし、配列がプログラムのコンテキストで生成された場合は失敗しますか?正確な比較ではなく、おおよその比較(たとえば、(array<10.20001) & (array>10.19999))を使用して比較の失敗を修正できますが、これは不満足なようです。

編集:配列内の値は、定数倍(例えば、0.2)の反復的な加算または減算によって生成されます。したがって、この配列の弾性率は、0.2はどこでも0に等しくなければなりません。

mod(array,0.2) 
... 
0.2000 
    0 
0.2000 
0.2000 
    0 

再び値を手動アレイおよびモジュラスに配置された場合、:アレイ内の数字の上記のシーケンスのために以下に示すように、実際には、各要素の弾性率は、0又は0.2のいずれかに等しいです。全ての期待値が得られる。

答えて

6

なぜなら、MATLABは配列内の数字を切り捨てて、表示するときに小数点以下4桁だけを保存するからです。つまり、配列の実際の値は[10.600000000001, -10.99999999999, ...]です。あなたが正しいのは、これはコンピュータの浮動小数点数の内部表現によるもので、計算に小さな誤差が生じる可能性があります。

個人的に私は2つの解決策があると思います.1つはおおよそのマッチングですが、もう1つは配列を最初に丸めて(たとえば、FileExchangeでthis toolとして)正確なマッチングを行うことです。

+0

非常に役に立ちます。 1つのフォローアップの質問は、私の数値がループ内の多くのサイクルにわたって一定量(例えば '0.2')を加算または減算することによって生成されたので、配列の数値は、modulo 0.2(' mod(array 、0.2) ')が適用される。実際、彼らはそうではありません。それらは0または0.2のいずれかに等しい。もちろん、配列の数値のいずれかにモジュロ0.2を手動で入力すると、期待値0が与えられます。あなたはこの行動を説明できますか?ありがとう! – user001

+1

これは、浮動小数点数がどのようにコンピュータに表示されるかを示します。よく知られている事実は、コンピュータが10進ではなくバイナリを使用することです。しかしながら、バイナリ、すなわち有限小数である問題があり、例えば小数点以下で0.2を2進数で有限桁で表すことはできない。つまり、コンピュータの0.2の2進表現は実際には0.001110011100111 ...です。これは無限です。ただし、MATLABは64ビットを使用して「Single」を表し、これは2 ^( - 65)の誤差を引き起こします。このエラーはかなり小さいですが、かなりの反復があると、それが蓄積する可能性があります。 – grapeot

+0

すばらしい説明。どうもありがとうございます。 – user001

2

おそらく何かがどこか単精度であり、他の場所では倍精度です。例えば、それぞれ10.2は異なるビット数の後に終了するので、それぞれ異なる。したがって、彼らは異なっている:

>> if (single(10.2) == 10.2) disp('honk'); end 
>> if (single(10.2) == single(10.2)) disp('honk'); end 
honk 

あなたは、いくつかの小さな違い内の等価性をチェックする必要があります

eps = 0.001; 
result = abs(array-10.2) < eps; 

あなたは玉葉を使用してアレイに使用される精度を見つけることができます。

>> whos A 
    Name  Size   Bytes Class  Attributes 

    A   1x2     8 single  
+0

ありがとう@Alex。あなたはgrapeotの投稿の下で私のコメントを見てください。ループの文脈で0.2(double)の一連の加算または減算によって生成された配列をとった場合、配列内のすべての要素のモジュロは0または0.2のいずれかであり、意味をなさない。 'whos'コマンド(ありがとう)を使って配列の精度をチェックしました。スカラーコンパレータ変数と同様に倍精度です。 – user001

+1

0.2は、バイナリ浮動小数点として正確に表現することはできません(http://www.h-schmidt.net/FloatApplet/IEEE754.htmlを参照)。これは連続した端数0.1001 [1001 ...]です。 0.2に何かを加えると、あなたの考えを正確にはできないかもしれません。正確性が重要な場合は、問題の最小単位で作業してください。この場合、おそらく10倍で作業し、数値に2を加えてmod(num、2)を確認し、最後に10を割ります。 – Alex

+0

ありがとうございました。この問題は、0.25を加算/減算することで解決されます。これは、指定したアプレットに応じて、0.25をバイナリ浮動小数点として正確に表すことができるため、理にかなっています。私は、より多くの情報を見つける最も良い場所は、数値の浮動小数点表現に関する記事になると思います。 – user001

1

モジュロ値(3〜9、つまりZ3〜Z9)を受け入れるMATLAB関数ファイルを作成し、 はモジュロ条件で記述可能な最小値を出力します。

サンプルシミュレーション:

Z = 3 4 5]。 %モジュロZ3、Z4、およびZ5

r = [2 1 4]; %の剰余は

最小限の値は、Z入力を使用する3から9までの任意の番号を入力し....とすることができますすることができ、アレイ行列...なければならない29.

ある値任意の順序で3,4,5,6,7,8,9を入力し、任意のペアまたはグループで...

R入力があまりにZ入力の数に等しくなければならない...

モジュロ条件を使用しても出力は最小値を返すはずです...

関連する問題