首页 > 解决方案 > 代码不适用于更大的 for 循环值

问题描述

我在 Matlab 中实现了一个 Szudik 的配对函数,其中我将来自 2 个不同矩阵 X 和 Y 的 2 个值配对为函数给出的唯一值 ' CantorPairing2D(X,Y),之后我反转该过程以检查它的可逆性由函数给出InverseCantorPairing2( X )'。但我似乎遇到了一个不寻常的问题,当我检查这个函数是否有大小为 10 * 10 的小矩阵时,它工作正常,但对于我的代码,我必须使用 256 * 256 矩阵 A 和 B,然后是代码出错了,实际上它给出的有点奇怪,因为当我反转过程时,矩阵 A 中的值在某些地方与 B 的 cvalues 相同,例如 A(1,1)=B(1,1 ),并且 A(1,2)=B(1,2)。有人可以帮忙吗。

VRNEW=CantorPairing2D(VRPRO,BLOCK3);

function [ Z ] = CantorPairing2D( X,Y )
[a,~] =(size(X));

Z=zeros(a,a);
for i=1:a
    for j=1:a
        if( X(i,j)~= (max(X(i,j),Y(i,j))) )
            Z(i,j)= X(i,j)+(Y(i,j))^2;
        else
            Z(i,j)= (X(i,j))^2+X(i,j)+Y(i,j);
        end
    end
end
Z=Z./1000;
end

function [ A,B ] = InverseCantorPairing2( X )
[a, ~] =(size(X));
Rfinal=X.*1000;
A=zeros(a,a);
B=zeros(a,a);
for i=1:a
    for j=1:a
        if(  ( Rfinal(i,j)- (floor( sqrt(Rfinal(i,j))))^2) < floor(sqrt(Rfinal(i,j))) )
            T=floor(sqrt(Rfinal(i,j)));
            B(i,j)=T;
            A(i,j)=Rfinal(i,j)-T^2;
        else
            T=floor(    (-1+sqrt(1+4*Rfinal(i,j)))/2      );
            A(i,j)=T;
            B(i,j)=Rfinal(i,j)-T^2-T;
        end
    end
end
end
      Example if     A= 45    16     7    17 
                         7    22    11    25
                        11    12     9    17                       
                         2    11     3     5                        

                      B=   0     0     0     1
                           0     0     0     1
                           1     1     1     1
                           1     3     0     0

          Then after pairing i get 
                      C =2.0700    0.2720    0.0560    0.3070
                         1.4060    0.5060    0.1320    0.6510
                         0.1330    0.1570    0.0910    0.3070
                         0.0070    0.1350    0.0120    0.0300    

在反向配对之后,我应该得到相同的 A 和相同的 B。但是对于更大的矩阵,它会给出不寻常的行为,因为 A 的某些元素与 B 相同。

标签: imagematlabfor-loopencodingfloating-point

解决方案


如果可能的话,这将极大地帮助您的代码失败的反例。

我必须重现您的代码行为,并以矢量化方式重写了您的代码。您应该得到错误,但希望这是发现底层逻辑并找到错误本身的第一步。

我不熟悉具体算法,但我观察到 CantorPairing 定义存在差异。

对于 Y = X 的元素,您的 if 语句将是错误的,因为 X = max(X,X); 因此对于这些元素,您的 Z 将为 X^2+X+Y,但对于假设 X =Y,因此您将有:X^2+X+X = X^2+2*X;

现在,如果我们稍微扰动方程并假设 Y = X + 10*eps,你的 if 语句将是真的(因为 Y > X)并且你的 Z 将是 X + Y ^2;因为 X ~=Y 我们可以近似为 X + X^2

因此,您的方程式对数值近似非常敏感(并且您肯定在 Z 中有不连续性)。同样,我不熟悉该算法,它很可能是您想要的行为,但不太可能:所以我要指出这一点。

以下是我的代码版本,我也报告它,因为我希望它有助于让您熟悉逻辑索引和矢量化代码(这是 MATLAB 的惯用形式,更不用说比嵌套 for 循环快得多了)。

function [ Z ] = CantorPairing2D( X,Y )
[a,~] =(size(X));

Z=zeros(a,a);

firstConditionIndeces = Y  >  X;  % if  Y > X then X is not the max between Y and X 
% update elements on which to apply first equation 
Z(firstConditionIndeces) = X(firstConditionIndeces) + Y(firstConditionIndeces).^2;

% update elements on the remaining elements
Z(~firstConditionIndeces) = X(~firstConditionIndeces).^2 + X(~firstConditionIndeces) + Y(~firstConditionIndeces) ; 

Z=Z./1000;
end


function [ A,B ] = InverseCantorPairing2( X )
[a, ~] =(size(X));
Rfinal=X.*1000;
A=zeros(a,a);
B=zeros(a,a);
T = zeros(a,a) ; 
% condition deciding which updates to be applied
indecesToWhichApplyFstFcn =  Rfinal- (floor( sqrt(Rfinal )))^2   < floor(sqrt(Rfinal)) ; 

% elements on which to apply the first update
T(indecesToWhichApplyFstFcn) = floor(sqrt(Rfinal )) ; 
B(indecesToWhichApplyFstFcn) = floor(Rfinal(indecesToWhichApplyFstFcn)) ;
A(indecesToWhichApplyFstFcn) = Rfinal(indecesToWhichApplyFstFcn) - T(indecesToWhichApplyFstFcn).^2;

% updates on which to apply the remaining elements
A(~indecesToWhichApplyFstFcn) = floor(    (-1+sqrt(1+4*Rfinal(~indecesToWhichApplyFstFcn  )))/2      ) ; 
B(~indecesToWhichApplyFstFcn) = Rfinal(~indecesToWhichApplyFstFcn) - T(~indecesToWhichApplyFstFcn).^2 - T(~indecesToWhichApplyFstFcn) ; 

end

推荐阅读