противоречивые результаты при использовании isreal - PullRequest
6 голосов
/ 30 августа 2010

Возьмите этот простой пример:

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

Что я делаю не так?

Ответы [ 3 ]

8 голосов
/ 30 августа 2010

Может быть полезно знать, что 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 указатель на комплексную часть всех значений в матрице.Поскольку все элементы хранятся вместе, то в этом случае все они имеют сложную часть.

Теперь сравните эти два подхода:

>> 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) имеет нулевую комплексную часть (ноль pi), поэтому считается действительным.

OneС другой стороны, ARRAYFUN, кажется, напрямую обращается к значениям матрицы (не возвращая их в переменной ANS), таким образом, он имеет доступ к указателям pr и pi, которые не равны нулю, поэтому все элементы считаются не-реально.

Пожалуйста, имейте в виду, что это только мое толкование, и я могу ошибаться ...

8 голосов
/ 30 августа 2010

Это, конечно, ошибка, но вот обходной путь:

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

ans =

     1     0

Почему это работает?Я не полностью уверен, но кажется, что когда вы выполняете операцию индексирования для переменной до вызова ISREAL , он удаляет "сложный" атрибут изэлемент массива, если мнимая составляющая равна нулю.Попробуйте это в Командном окне:

>> 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 , таким образом обрабатываявсе они являются комплексными числами, даже если мнимая составляющая равна нулю.

3 голосов
/ 26 января 2012

Ответ на этот вопрос очень поздно ... Функция 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 действительно нужна функция, которая отвечает на вопрос "имеет ли это значение нулевую мнимую часть" поэлементно в массиве.

...