当条目很复杂并且舍入错误导致问题时,删除向量中的重复条目

时间:2012-04-23 19:02:04

标签: matlab

我想从Matlab上的向量中删除重复的条目。我遇到的问题是,舍入错误会阻止内置的Matlab函数“独特”正常工作。理想情况下,我想要一种方法来对“唯一”函数设置某种容差,或者是一个小程序,否则将删除重复项。如果两个条目的实部和虚部相差小于0.0001,那么我很高兴认为它们相等。我怎么能这样做?

任何帮助将不胜感激。感谢

3 个答案:

答案 0 :(得分:4)

简单的近似是对数字进行舍入,并使用unique返回的索引:

X = ... (input vector)
[b, i] = unique(round(X / (tolerance * (1 + i))));
output = X(i);

(根据您的Matlab版本,您可以将b替换为~

它不会有你想要的行为,因为两个数字可能非常接近,但会以不同的方式舍入。我认为你可以通过以下方式缓解这个问题:

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);

这会将它们四舍五入,因此任何正好在舍入边界上的数字都会被第二个unique捕获。 在这方面仍然存在一些混乱 - 一些数字会受到影响,就好像容差加倍一样。但它可能足以满足您的需求。

替代方案可能是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));

我认为这具有您可以预期的最佳行为(因为您希望通过尽可能少的唯一值来表示向量 - 当有许多数字相差小于容差级别时,可能有多种方式这个算法非常贪婪,从最小的算法开始。

答案 1 :(得分:0)

我几乎可以肯定,下面的疾病总是假设任何接近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

答案 2 :(得分:0)

以下内容可能符合您的目的。给定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],甚至虽然你可能会考虑,例如,X_unique = [1 + i,4 + 4i]也是一个有效的答案。