举个简单的例子:
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
我究竟做错了什么?
知道 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
非空指针,因此所有元素都被视为非实数。
请记住这只是我的解释,我可能会弄错......
这当然似乎是一个错误,但这里有一个解决方法:
>> 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的数组元素的“复数”属性,因此即使虚部为零,也将它们全部视为复数。
回答这个问题真的很晚...... 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 确实需要一个函数来以数组的元素方式回答“这个值的虚部是否为零”这个问题。