3

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

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

4

3 回答 3

4

一个简单的近似是对数字进行四舍五入并使用唯一返回的索引:

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

我认为这具有您可以期望的最佳行为(因为您希望用尽可能少的唯一值来表示向量 - 当有很多数字的差异小于容差水平时,可能有多种拆分它们的方法。这个算法贪婪地做,从最小的开始)。

于 2012-04-23T19:37:13.523 回答
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] 也是一个有效答案。

于 2014-10-30T04:48:22.110 回答
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
于 2012-04-23T21:11:35.627 回答