Matlab のベクターから重複したエントリを削除したいと考えています。私が抱えている問題は、丸め誤差が組み込みの Matlab 関数 'unique' を適切に機能させないことです。理想的には、「一意の」機能に何らかの許容範囲を設定する方法、または重複を削除する小さな手順が必要です。2 つのエントリの実数部と虚数部の差が 0.0001 未満の場合は、喜んで等しいと見なします。これどうやってするの?
どんな助けでも大歓迎です。ありがとう
Matlab のベクターから重複したエントリを削除したいと考えています。私が抱えている問題は、丸め誤差が組み込みの Matlab 関数 'unique' を適切に機能させないことです。理想的には、「一意の」機能に何らかの許容範囲を設定する方法、または重複を削除する小さな手順が必要です。2 つのエントリの実数部と虚数部の差が 0.0001 未満の場合は、喜んで等しいと見なします。これどうやってするの?
どんな助けでも大歓迎です。ありがとう
簡単な概算は、数値を丸め、unique によって返されるインデックスを使用することです。
X = ... (input vector)
[b, i] = unique(round(X / (tolerance * (1 + i))));
output = X(i);
( Matlab のバージョンによっては、b
おそらく置き換えることができます)。~
2 つの数値が非常に近いが、丸め方が異なる可能性があるため、希望する動作にはなりません。次のようにすることでこれを軽減できると思います。
X = ... (input vector)
[b, ind] = unique(round(X / (tolerance * (1 + i))));
X = X(ind);
[b, ind] = unique(round(X / (tolerance * (1 + i)) + 0.5 * (1 + i)));
X = X(ind);
これにより、それらが 2 回丸められるため、丸め境界に正確にある数値は、2 番目に捕捉されunique
ます。これにはまだ多少の混乱があります。許容値が 2 倍になったかのように影響を受ける数値もあります。しかし、それはあなたのニーズには十分かもしれません.
代替手段はおそらくfor
ループです:
X = sort(X);
last = X(1);
indices = ones(numel(X), 1);
for j=2:numel(X)
if X(j) > last + tolerance * (1 + i)
last = X(j) + tolerance * (1 + i) / 2;
else
indices(j) = 0;
end
end
X = X(logical(indices));
これは期待できる最良の動作だと思います (できるだけ少ない一意の値でベクトルを表現したいため、許容レベル未満で異なる数値が多数ある場合、それらを分割する方法が複数ある場合があります。このアルゴリズムは、最小のものから始めて、貪欲に行います)。
以下はあなたの目的に役立つかもしれません。複素 double の配列である X を指定すると、それらを並べ替え、要素間の絶対値の差が複素許容誤差 real_tol および imag_tol 内にあるかどうかをチェックします。この許容範囲を満たす要素を削除します。
function X_unique = unique_complex_with_tolerance(X,real_tol,imag_tol)
X_sorted = sort(X); %Sorts by magnitude first, then imaginary part.
dX_sorted = diff(X_sorted);
dX_sorted_real = real(dX_sorted);
dX_sorted_imag = imag(dX_sorted);
remove_idx = (abs(dX_sorted_real)<real_tol) & (abs(dX_sorted_imag)<imag_tol);
X_unique = X_sorted;
X_unique(remove_idx) = [];
return
このコードは、この差の許容範囲を満たすすべての要素を削除することに注意してください。たとえば、X = [1+i,2+2i,3+3i,4+4i]、real_tol = 1.1、imag_tol = 1.1 の場合、この関数は X_unique = [4+4i] の 1 つの要素のみを返します。たとえば、 X_unique = [1+i,4+4i] も有効な答えであると考えるかもしれません。
以下は、1e-8 に近い値はすべて等しいと常に仮定しているとほぼ確信しています。1e-8 を任意の値に置き換えるだけです。
% unique function that assumes 1e-8 is equal
function [out, I] = unique(input, first_last)
threshold = 1e-8;
if nargin < 2
first_last = 'last';
end
[out, I] = sort(input);
db = diff(out);
k = find(abs(db) < threshold);
if strcmpi(first_last, 'last')
k2 = min(I(k), I(k+1));
elseif strcmpi(first_last, 'first')
k2 = max(I(k), I(k+1));
else
error('unknown flag option for unique, must be first or last');
end
k3 = true(1, length(input));
k3(k2) = false;
out = out(k3(I));
I = I(k3(I));
end