Incorrect results from intersect when entering imaginary numbers

The attached file, data1.txt, contains the X-Y coordinates of the points in Set A.
The other file, data2.txt, contains the X-Y coordinates of the points in Set B.
My objective is to find the intersection of the two sets.
I used intersect() in MATLAB in three ways but got different answers.
First way, combining the X array and the Y array in the same set as table(X, Y) and then input the two tables to intersect();
Second way, combining the X array, Y array in the same set as X+1i.*Y and then input the two imaginary number arrays to intersect();
Third way, combining the X array, Y array in the same set as X+100.*Y and then input the two real number arrays to intersect().
I found the answers from the first two ways were wrong!

1 Comment

Can you expand on what you mean by the first two ways were wrong? From what I can tell all three methods produce the same result (other than how the values are sorted)...
load('data1.txt')
load('data2.txt')
% I think these are the three ways you used intersect:
t1=table(data1(:,1),data1(:,2));
t2=table(data2(:,1),data2(:,2));
res1=intersect(t1,t2);
res2=intersect(data1(:,1)+data1(:,2)*1i,data2(:,1)+data2(:,2)*1i);
res3=intersect(data1(:,1)+data1(:,2)*100,data2(:,1)+data2(:,2)*100);
% Here's an alternative that doesn't use intersect:
res_alt=data2(ismember(data2,data1(ismember(data1,data2,'rows'),:),'rows'),:);
% Are the the same number of elements?
height(res1)==height(res2)
ans = logical
1
height(res1)==height(res3)
ans = logical
1
height(res1)==height(res_alt)
ans = logical
1
% Decompose the complex back into real components and sort rows to compare with res1:
isequal(sortrows(table2array(res1)), sortrows([real(res2) imag(res2)]))
ans = logical
1
% Decompose the *100 out of res3
res3_y=(floor(res3/50)*50)/100;
res3_x=res3-res3_y*100;
a=sortrows(table2array(res1))-sortrows([res3_x res3_y]);
% some floating point error is to be expected, right?
max(abs(sort(res1.Var1)-sort(res3_x)))
ans = 9.1038e-14
max(abs(sort(res1.Var2)-sort(res3_y)))
ans = 0
% check res1 against res_alt
isequal(sortrows(table2array(res1)), sortrows(res_alt))
ans = logical
1

Sign in to comment.

Answers (2)

A = readmatrix('data1.txt')
A = 465×2
0.4000 1.5000 0.6000 1.5000 0.8000 1.5000 1.0000 1.5000 1.2000 1.5000 1.4000 1.5000 1.8000 1.5000 2.0000 1.5000 0.4000 2.0000 0.6000 2.0000
B = readmatrix('data2.txt')
B = 408×2
0.2000 1.5000 0.4000 1.5000 0.6000 1.5000 0.8000 1.5000 1.0000 1.5000 1.2000 1.5000 1.4000 1.5000 1.6000 1.5000 1.8000 1.5000 0.2000 2.0000
C = intersect(A,B,'rows')
C = 388×2
0.2000 1.5000 0.2000 2.0000 0.2000 2.5000 0.2000 3.0000 0.2000 3.5000 0.2000 4.0000 0.2000 4.5000 0.2000 5.0000 0.2000 5.5000 0.2000 6.0000
In my application, the actual situation is like running the following scripts in R2021a.
clear
load('A.mat','overturn_Pi_p','overturn_Pi_a');
A = table(overturn_Pi_p, overturn_Pi_a);
load('B.mat','overturn_Pi_p','overturn_Pi_a');
B = table(overturn_Pi_p, overturn_Pi_a);
%First way gives the wrong answer 232
height(intersect(A, B))
%Second way gives the wrong answer 232
A_comb1 = A.overturn_Pi_p + 1i.*A.overturn_Pi_a;
B_comb1 = B.overturn_Pi_p + 1i.*B.overturn_Pi_a;
length(intersect(A_comb1, B_comb1))
%Third way gives the correct answer 388
A_comb2 = A.overturn_Pi_p + 100.*A.overturn_Pi_a;
B_comb2 = B.overturn_Pi_p + 100.*B.overturn_Pi_a;
length(intersect(A_comb2, B_comb2))

3 Comments

My guess is you're seeing different results because of floating point error. I already see a small difference between the values in B.mat and the values in data1.txt. When you multiply by 100 the change in precision produces a different result. intersect does not accept a tolerance, it just uses strict equality.
You can find a nice answer here:
load('B.mat','overturn_Pi_p','overturn_Pi_a');
B = table(overturn_Pi_p, overturn_Pi_a);
B_txt=readtable('data1.txt');
histogram(B_txt.Var1-B.overturn_Pi_p)
Thank you, Dave! You are absolutely right.
Now I can get identical answer from the three approaches after modifying the codes as below to get rid of the floating point error.
The array overturn_Pi_p was generated elsewhere by assigning 0.2:0.2:8 to it with certain filtering criterion and then saved it to *.mat. This process causes floating point error!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
load('A.mat','overturn_Pi_p','overturn_Pi_a');
overturn_Pi_p=round(overturn_Pi_p.*10)./10;
overturn_Pi_a=round(overturn_Pi_a.*10)./10;
A = table(overturn_Pi_p, overturn_Pi_a);
load('B.mat','overturn_Pi_p','overturn_Pi_a');
overturn_Pi_p=round(overturn_Pi_p.*10)./10;
overturn_Pi_a=round(overturn_Pi_a.*10)./10;
B = table(overturn_Pi_p, overturn_Pi_a);
......
I wish all of the set operations had a tolerance option!

Sign in to comment.

Products

Release

R2021a

Asked:

on 23 Oct 2021

Commented:

on 26 Oct 2021

Community Treasure Hunt

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

Start Hunting!