この簡単な例を見てください。
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
私は何が間違っているのですか?
この簡単な例を見てください。
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
私は何が間違っているのですか?
これは確かにバグのようですが、回避策は次のとおりです。
>> 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に渡す配列要素の「複素数」属性を内部的に維持する必要があるため、虚数成分がゼロの場合でも、それらすべてを複素数として扱います。
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ではないポインターpr
とpi
ポインターの両方にアクセスできます。したがって、すべての要素は非実数と見なされます。
これは私の解釈であり、誤解される可能性があることを覚えておいてください...
これについては本当に遅れて答えています...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には、配列上で要素ごとに「この値の虚数部がゼロか」という質問に答える関数が本当に必要です。