6

この簡単な例を見てください。

a = [1 2i];

x = zeros(1,length(a));
for n=1:length(a)
    x(n) = isreal(a(n));
end

コードをベクトル化するために、私は次のことを試みました。

y = arrayfun(@isreal,a);

しかし、結果は同じではありません。

x =
     1     0
y =
     0     0

私は何が間違っているのですか?

4

3 に答える 3

8

これは確かにバグのようですが、回避策は次のとおりです。

>> y = arrayfun(@(x) isreal(x(1)),a)

ans =

     1     0

なぜこれが機能するのですか?完全にはわかりませんが、 ISREALを呼び出すに変数に対してインデックス作成操作を実行すると、虚数成分がゼロの場合、配列要素から「complex」属性が削除されるようです。コマンドウィンドウでこれを試してください。

>> a = [1 2i];         %# A complex array
>> b = a(1);           %# Indexing element 1 removes the complex attribute...
>> c = complex(a(1));  %# ...but we can put that attribute back
>> whos
  Name       Size            Bytes  Class      Attributes

  a          1x2                32  double     complex   
  b          1x1                 8  double                  %# Not complex
  c          1x1                16  double     complex      %# Still complex

どうやら、ARRAYFUNは、 ISREALに渡す配列要素の「複素数」属性を内部的に維持する必要があるため、虚数成分がゼロの場合でも、それらすべてを複素数として扱います。

于 2010-08-30T17:54:14.623 に答える
8

MATLABが行列の実数部/複素数部を別々に格納することを知っておくと役立つ場合があります。次のことを試してください。

>> format debug
>> a = [1 2i];
>> disp(a)

Structure address = 17bbc5b0 
m = 1
n = 2
pr = 1c6f18a0 
pi = 1c6f0420
   1.0000                  0 + 2.0000i

ここprで、はすべての値の実数部を含むメモリブロックへのポインタ、およびpi行列内のすべての値の複素数部へのポインタです。すべての要素が一緒に保存されるため、この場合、それらはすべて複雑な部分を持ちます。

次に、これら2つのアプローチを比較します。

>> arrayfun(@(x)disp(x),a)

Structure address = 17bbcff8 
m = 1
n = 1
pr = 1bb8a8d0 
pi = 1bb874d0
     1

Structure address = 17c19aa8 
m = 1
n = 1
pr = 1c17b5d0 
pi = 1c176470
        0 + 2.0000i

>> for n=1:2, disp(a(n)), end

Structure address = 17bbc930 
m = 1
n = 1
pr = 1bb874d0 
pi = 0
     1

Structure address = 17bbd180 
m = 1
n = 1
pr = 1bb874d0 
pi = 1bb88310
        0 + 2.0000i

a(1)したがって、forループでアクセスすると、(ans変数で)返される値の複素数部分(null pi)がゼロであるため、実数と見なされるようです。

一方、ARRAYFUNはマトリックスの値に直接アクセスしているようです(ANS変数でそれらを返さずに)。したがって、 nullではないポインターprpiポインターの両方にアクセスできます。したがって、すべての要素は非実数と見なされます。

これは私の解釈であり、誤解される可能性があることを覚えておいてください...

于 2010-08-30T18:52:08.720 に答える
3

これについては本当に遅れて答えています...MATLAB関数ISREALは、多くの目的で非常に直感に反する方法で動作します。全体として特定の配列に複雑な部分がまったくないかどうかがわかります。ストレージについてはわかりますが、配列内のについては実際には何もわかりません。その点では、ISSPARSE関数に少し似ています。だから、例えば

isreal(complex(1)) % returns FALSE

MATLABにあるのは、特定の操作によって、すべてゼロの虚数部が自動的にトリミングされることです。だから、例えば

x = complex(1);
isreal(x); % FALSE, we just forced there to be an imaginary part
isreal(x(1)); % TRUE - indexing realised it could drop the zero imaginary part
isreal(x(:)); % FALSE - "(:)" indexing is just a reshape, not real indexing

つまり、MATLABには、配列上で要素ごとに「この値の虚数部がゼロか」という質問に答える関数が本当に必要です。

于 2012-01-26T08:14:32.670 に答える