column operator erases complex property
1 次查看(过去 30 天)
显示 更早的评论
Why column (:) changes my data? (R2020b)
>> z=complex(3,0)
z =
3.000000000000000 + 0.000000000000000i
>> isreal(z)
ans =
logical
0
>> isreal(reshape(z,[],1))
ans =
logical
0
>> isreal(z(:)) %%%% <= only column returns 1
ans =
logical
1
21 个评论
Walter Roberson
2020-10-18
Interesting. I wonder if debugging would show a different data pointer, unlike reshape?
Bruno Luong
2020-10-18
编辑:Bruno Luong
2020-10-18
The weird thing is actually no, the pointer stays the the same with format debug
I believe there are a flag of complex in the mxArray structure, this one must (wrongly?) be set by (:)
>> z
Structure address = 1b8e0bac460
m = 1
n = 1
pr = 1b8f7d92e20
3.0000 + 0.0000i
>> reshape(z,[],1)
Structure address = 1b8e0bac460
m = 1
n = 1
pr = 1b8f7d92e20
3.0000 + 0.0000i
>> z(:)
Structure address = 1b8e0bac460
m = 1
n = 1
pr = 1b8f7d92e20
3
VBBV
2020-10-18
编辑:VBBV
2020-10-18
Bcoz z is declared using complex function with two arguments, real numbès 3 and 0. The output is one complex number with one row and one col. For which the real part exists and equal to 3.
Use of : operator makes z as vector with two col and one row. So may be using it isreal(z(:)) makes z as real vector with real values only
Bruno Luong
2020-10-18
编辑:Bruno Luong
2020-10-18
@Vasishta, Na. Your explanation does not make sense.
z(:)
should be the same as
reshape(z,[],1)
and it's one row one column and I expected it remains complex, as Z.
VBBV
2020-10-18
@Bruno I told how matlab function isreal() is assuming complex number in this special case Thru the use of : operator. May be you can consider it as bug in 2020b
Walter Roberson
2020-10-18
Vasishta:
When you use : as the only subscript, the result always has exactly 1 column, even if the original array had dimensions that were only 0 such as zeros(0,0)
Paul
2020-10-18
Seems like any kind of indexing loses the complex attribute:
>> z
z =
3.0000 + 0.0000i
>> isreal(z(1)),isreal(z(1,1)),isreal(z(true))
ans =
logical
1
ans =
logical
1
ans =
logical
1
VBBV
2020-10-18
编辑:Walter Roberson
2020-10-19
@Bruno See the Information in Tips section of the documentation link
VBBV
2020-10-19
编辑:Walter Roberson
2020-10-19
@ Bruno
z = complex(12,1);
z =
12.0000 + 1.0000i
isreal(z(:))
ans =
logical
0
So zero is special case
VBBV
2020-10-19
@ Walter
Ok. What I had thought is use of only : operator in a matrix considers all rows and all cols of matrix
Walter Roberson
2020-10-19
编辑:Walter Roberson
2020-10-19
Visashta:
The Tips section of complex() is telling you that complex() is a special function that can explicitly construct variables that have complex part that is all zero, but that the form A+B*i is considered an expression adding A and i*B and that since that is an expression, any all-zero imaginary part will be dropped.
Yes, complex part all-zero is a special case in MATLAB, and the boundaries of that special case are exactly what we are exploring here. It has always been the case that an all-zero complex part will not be lost when you copy or pass a variable, but that it would normally be lost if you use the variable in an expression. The question then arises whether calling reshape() or indexing with (:) should be considered an expression for the purposes of losing the all-zero part. Bruno demonstrated that reshape() does not lose the all-zero complex component, which fits in with the known implementation of reshape() as being about changing the dimension header while using exactly the same data pointer(s) .
Indexing with (:) has long been discussed as being a short-cut for reshape() into a column vector, and if that is the case then because reshape() does not lose the all-zero complex part, it would be unexpected that (:) would lose the all-zero complex part.
We can then ask the question of whether (:) is instead considered an expression rather than just a shortcut to reshape() into a single column. But if it were an expression, then we would expect that for real-valued z, z(:) would copy the data instead of sharing it, leading to a different data pointer. A minor bit of testing shows that is not the case, that when z only contains real values that z(:) shares data.
So... z(:) with complex z is somehow being treated specially, and losing all-zero complex part. z(:) with complex z is giving back a different data pointer.
Next we test
>> format debug
>> z = complex([1 2 3],4)
z =
Structure address = 1dc3db9a0
m = 1
n = 3
pr = 6040044bac60
1.0000 + 4.0000i 2.0000 + 4.0000i 3.0000 + 4.0000i
>> reshape(z,[],1)
ans =
Structure address = 1dc3d95a0
m = 3
n = 1
pr = 6040044bac60
1.0000 + 4.0000i
2.0000 + 4.0000i
3.0000 + 4.0000i
>> z(:)
ans =
Structure address = 1dc3d8d00
m = 3
n = 1
pr = 608005e83260
1.0000 + 4.0000i
2.0000 + 4.0000i
3.0000 + 4.0000i
Notice that when we did the reshape() that the data pointer stayed the same, but when we did the (:) that the data pointer changed. That does not happen when z has no complex part.
>> z1 = [1 2 3]
z1 =
Structure address = 1dc3da500
m = 1
n = 3
pr = 60800d076ca0
1 2 3
>> reshape(z1,[],1)
ans =
Structure address = 1dc3d9c60
m = 3
n = 1
pr = 60800d076ca0
1
2
3
>> z1(:)
ans =
Structure address = 1dc3d8d00
m = 3
n = 1
pr = 60800d076ca0
1
2
3
The problem therefor expands a bit beyond what Bruno originally posted, becoming instead the question:
What is (:) treated like an expression for complex z, but treated as reshape() for non-complex z?
With it being treated as an expression, losing the all-zero part would be automatic.
Walter Roberson
2020-10-19
Bruno's original example shows the same data pointer for scalar z. With non-scalar z, the data pointer is changed.
Other forms of indexing are expected to be treated as an expression.
>> z1 = [1 2 3]
z1 =
Structure address = 1dc3da500
m = 1
n = 3
pr = 60800d076ca0
1 2 3
>> z1(:)
ans =
Structure address = 1ed9c1960
m = 3
n = 1
pr = 60800d076ca0
1
2
3
>> z1(1:3)
ans =
Structure address = 19e7fcb20
m = 1
n = 3
pr = 60800d06ffa0
1 2 3
This is at least consistent between real and complex: this kind of indexing creates new data structures even for real-only data. It is also explicitly documented as creating unshared data: indexing at 1:end in particular is the documented way to create unshared copies of objects (though at the moment I do not recall at the moment whether it creates deep or shallow copies.)
Bruno Luong
2020-10-19
编辑:Bruno Luong
2020-10-19
@Vanishta, you miss my point, the COMPLEX command allocates real+imaginary internally, even if imagnary part is 0. That is user intention of using complex command.
The whole purpose of the TIP part of the document is actually tells that user is allowed to create complex array with 0s value in imaginary part.
I expect (:) to preserve that allocation (and keep the data pointer constant) as with RESHAPE. Which is NOT the case.
Why doing such thing, you might ask? Because if I do change a subset of elements of the initial array, it will be faster (assumming array are not shared)
>> format debug
>> z=complex(1:3,0)
z =
Structure address = 2258b2d6a40
m = 1
n = 3
pr = 225a25023c0
1.0000 + 0.0000i 2.0000 + 0.0000i 3.0000 + 0.0000i
>> z(3)=1i % I might do this kind of assigment in for-loop
z =
Structure address = 2258b2d6a40
m = 1
n = 3
pr = 225a25023c0
1.0000 + 0.0000i 2.0000 + 0.0000i 0.0000 + 1.0000i
Unfortunately (:) operator would erase my allocation with COMPLEX.
Bruno Luong
2022-3-28
编辑:Bruno Luong
2022-3-28
Some unexpected side-effect that could surprise some users:
z=complex([-2; 1]);
sort(z)
ans =
1.0000 + 0.0000i
-2.0000 + 0.0000i
sortrows(z)
ans = 2×1
1
-2
sort(z(:))
ans = 2×1
-2
1
Bruno Luong
2022-3-28
It seems
- sortrows works on complex input then decide to "cast" the sorted result to real.
- sort(z) does not post cast.
- Whereas sort(z(:)) cast the input first.
Walter Roberson
2022-3-29
The part I was forgetting was this from sort:
- If A is complex, then by default, sort sorts the elements by magnitude. If more than one element has equal magnitude, then the elements are sorted by phase angle on the interval (−π, π].
But these days there is a 'ComparisonMethod' option, of 'real' or 'magnitude'
采纳的回答
Walter Roberson
2020-10-18
For reasons I do not understand, z(:) is being treated as an expression. If you make z larger but complex, then reshape(z,[],1) keeps the same data pointer, but z(:) creates a new data pointer each time -- which is not the case if z is not complex.
I have two speculations at the moment:
- Hypothetically, since array indexing is treated as an expression, Mathworks might have wanted consistency around dropping the complex part of expressions when the complex part was all zero. This explanation is a bit weak as it does not explain why they did not treat reshape() the same way, and does not explain why scalar z keeps the same data pointer (but non-scalar z does not.)
- Hypothetically, it might have to do with the change to representation of complex in R2018a. This explanation is a bit weak as it does not explain why they did not treat reshape() the same way, and does not explain why scalar z keeps the same data pointer (but non-scalar z does not.) On the other hand, this hypothesis has the merit that it would be testable by going back to R2017b and seeing if (:) had the same behaviour there.
7 个评论
per isakson
2020-10-19
>> z=complex(3,0)
z =
3.0000 + 0.0000i
>> isreal(z)
ans =
logical
0
>> isreal(z(:))
ans =
logical
1
>> version
ans =
'9.3.0.713579 (R2017b)'
>>
Walter Roberson
2020-10-19
Thanks, per... that eliminates (2) .
z(:) is also supposed to be z(1:end) but z(1:end) is documented as making copies. There thus seems to be a conflict here between whether z(:) is z(1:end) "copied" or is reshape(z,[],1) (uncopied), and that conflict seems to be resolved different ways depending upon whether z is real-only or has complex components.
Bruno Luong
2020-10-19
Walter; I too guess it's 1).
To me (:) would be less intrusive than what I just discover. I have tendency to use it a lot, but possibly I would think twice now.
Walter Roberson
2020-10-19
Hmmm... what is the difference between
z(:)
subsref(z,struct('type',{'()'}, 'subs', {{':'}}))
The second of those always creates a new data pointer even for real data, but the first of them does not create a new data pointer for real-valued z, or for scalar complex valued z (but the scalar part potentially loses complex 0)
Jan
2021-7-28
@Bruno Luong: You are Bruno. Just write them an email and ask for an explanation. From time to a developper has called by by phone to explain details concerning a discussion in the forum. They are interested in active users.
更多回答(0 个)
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)