противоречивые результаты с использованием isreal

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

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

Что я делаю неправильно?


person Dave    schedule 30.08.2010    source источник
comment
Какую версию MATLAB вы используете?   -  person bta    schedule 30.08.2010
comment
Вы сообщили об ошибке в MathWorks?   -  person Jonas    schedule 30.08.2010
comment
@bta: я использую последнюю версию MATLAB. @Jonas: не совсем, обычно я виню себя, а не программу :)   -  person Dave    schedule 30.08.2010


Ответы (3)


Это, безусловно, похоже на ошибку, но вот обходной путь:

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

person gnovice    schedule 30.08.2010
comment
Кстати, ошибка не появляется в GNU Octave. - person kennytm; 30.08.2010
comment
вы правы, согласно документации функции КОМПЛЕКС, isreal(1+0i) не то же самое, что isreal(complex(1,0)) - person Dave; 30.08.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) имеет нулевую сложную часть (null pi), поэтому считается реальным.

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

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

person Amro    schedule 30.08.2010
comment
Я должен поблагодарить @Mikhail за этот совет: вектор ublas из массива ac"> stackoverflow.com/questions/1735841/ (см. комментарии) - person Amro; 30.08.2010

Очень поздно отвечаю на этот вопрос... Функция MATLAB ISREAL работает довольно нелогичным образом для многих целей. Он говорит вам, что данный массив, взятый в целом, вообще не имеет сложной части — он говорит вам о хранилище, но ничего не говорит вам о < em>значения в массиве. В этом отношении она немного похожа на функцию 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 действительно нужна функция, которая отвечает на вопрос «имеет ли это значение нулевую мнимую часть» поэлементно в массиве.

person Edric    schedule 26.01.2012