arrayfun isreal fails - how to fix?

1 visualización (últimos 30 días)
Alan
Alan el 7 de Ag. de 2019
Editada: Stephen23 el 9 de Ag. de 2019
x = randn(8,1);
z = fft(x);
assert(isreal(z(1)),'First');
y = arrayfun(@isreal,z);
assert(y(1),'Second');
In this snippet, I am trying to create a function which will return those elements in an array that are real.
The first assert passes, the first element of z is real.
The second assert fails as y thinks that every element in the array is not real.
Why?
How do I write a function that check whether each element in an array is real. Do I have to use a loop?
  3 comentarios
Alan
Alan el 7 de Ag. de 2019
But z(1) is an array of size 1x1. Isn't everything an array in MATLAB?
And
isreal(z(1))
is true.
And the documentation for arrayfun says it applies the function func to the elements of A, one element at a time. So my code applies isreal to z(1) yet returns false.
Stephen23
Stephen23 el 8 de Ag. de 2019
Editada: Stephen23 el 9 de Ag. de 2019
"Isn't everything an array in MATLAB?"
Yes. What you have uncovered is either inconsistent in arrayfun or the indexing, but either way is irrelevant to the question that you asked: "How do I write a function that check whether each element in an array is real." That is what I explained in my previous comment: being real or complex is a property of the entire array, so there is absolutely no point in testing each individual element. You seem to be confusing the values (i.e. having zero imaginary value) with an array property (real array vs. complex array).
Your question is like asking "how can I check if each element of a numeric array is numeric": of course each element of a numeric array is numeric. Ditto for real/complex arrays.
Test if the imaginary value is zero:
not(imag(z))

Iniciar sesión para comentar.

Respuestas (2)

Guillaume
Guillaume el 7 de Ag. de 2019
Note that the problem you highlight has nothing to do with isreal. I guess that you've uncovered an unexpected implementation detail of arrayfun. When dealing with complex numbers, it is not exactly equivalent to a loop.
First, some non-random testing data:
thetad = (0:90:360)';
z = cosd(thetad) + 1i*sind(thetad)
Simple test, let's extract each number into a cell array with a loop and with arrayfun:
>> carrayfun = arrayfun(@(x) x, z, 'UniformOutput', false)
carrayfun =
5×1 cell array
{[ 1 + 0i]}
{[ 0 + 1i]}
{[-1 + 0i]}
{[ 0 - 1i]}
{[ 1 + 0i]}
As you can see, each element is still complex, even those with imaginary part 0.
Now, with the equivalent loop:
>> cloop = cell(size(z)); for idx = 1:numel(z), cloop{idx} = z(idx); end; cloop
cloop =
5×1 cell array
{[ 1]}
{[0 + 1i]}
{[ -1]}
{[0 - 1i]}
{[ 1]}
The pure real elements are extracted as pure real. Note that num2cell does the same:
>> num2cell(z)
ans =
5×1 cell array
{[ 1]}
{[0 + 1i]}
{[ -1]}
{[0 - 1i]}
{[ 1]}
So, it must be an oddity of arrayfun, probably some optimisation detail. Probably worthy of a bug report to mathworks (if only so that the documentation explains what happens).
  5 comentarios
Bruno Luong
Bruno Luong el 8 de Ag. de 2019
Editada: Bruno Luong el 8 de Ag. de 2019
Well the integer/complex field is a quite interesting math object, you can do operation like any better-known fields, but have some odd (but interesting) properties such as decomposition in prime "numbers" is not unique. I believe Gauss is the first one who are interested in such field.
People writing MEX interested in internal storage, but I think in case I don't care at all about how ARRAYFUN/CELLFUN behaves. I really use them, or when I use thme is by laziness.
I guess the odd effect we are discussing is due to TMW attempt to accelerate at all cost ARRAYFUN. I don't need them to document such special behavior, they are free to do whatevever they like.
James Tursa
James Tursa el 8 de Ag. de 2019
Editada: James Tursa el 8 de Ag. de 2019
The problem with z == real(z) (and other methods posted here) is that it creates a temporary data copy of the real part of z. If you are working with large variables you don't really want that to happen. It would be nice if TMW included a function for this directly that didn't create this copy in the background. For now I guess we have to resort to mex routines to avoid the data copy.

Iniciar sesión para comentar.


Bruno Luong
Bruno Luong el 7 de Ag. de 2019
Editada: Bruno Luong el 7 de Ag. de 2019
Guys ISREAL tests whereas the internal storage of an array does not allocated memory for the imaginary part, it is NOT testing the imaginary part is 0.
In recent MATLAB you can do this:
>> a = 1
a =
1
>> isreal(a)
ans =
logical
1
>> b=complex(a)
b =
1.0000 + 0.0000i
>> b==a
ans =
logical
1
>> isreal(b)
ans =
logical
0

Categorías

Más información sobre Matrices and Arrays en Help Center y File Exchange.

Etiquetas

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by