R2015a中引入的uniquetol
函数计算“公差范围内的唯一元素”明确地,C = uniquetol(A,tol)
使用toleranceA
返回tol
中的唯一元素。
但是找到具有给定公差的唯一元素的问题有几个解决方案哪一个是实际生产的?
让我们看两个例子:
设绝对公差A = [3 5 7 9]
输出可以是2.5
,也可以是[3 7]
两种方案均满足要求。
对于绝对公差[5 9]
的A = [1 3 5 7 9]
,输出可以是2.5
或[1 5 9]
因此,即使输出中的元素数量也可能有所不同。
关于问题核心的及物性问题,请参见this nice discussion。
那么,[3 7]
是如何工作的呢它在多个现有解决方案中产生了什么输出?
最佳答案
为了简化,我考虑一个输出,两个输入版本的uniquetol
,
C = uniquetol(A, tol);
其中第一个输入是向量特别是,这意味着:
未使用
double
选项。第一个输入是向量如果不是这样,
A
会像往常一样隐式地线性化到列。定义公差的第二个输入被解释为:
如果
'ByRows'
也就是说,默认情况下指定的公差是相对的在比较中使用的实际公差是通过在
uniquetol
中的最大绝对值缩放得到的。考虑到这些因素,
uniquetol
使用的方法似乎是:排序
u
。选择sorted
v
的第一个条目,并将其设置为参考值(该值稍后必须更新)。将参考值写入输出
abs(u-v) <= tol*max(abs(A(:)))
。跳过已排序
A
的后续条目,直到找到不在参考值公差范围内的条目找到该条目后,将其作为新的参考值并返回到步骤3。当然,我不是说这就是
uniquetol
内部所做的但产出似乎是一样的所以这在功能上等同于A
的作用。下面的代码实现了上面描述的方法(低效的代码,只是为了说明这一点)。
% Inputs A, tol
% Output C
tol_scaled = tol*max(abs(A(:))); % scale tolerance
C = []; % initiallize output. Will be extended
ref = NaN; % initiallize reference value to NaN. This will immediately cause
% A(1) to become the new reference
for a = sort(A(:)).';
if ~(a-ref <= tol_scaled)
ref = a;
C(end+1) = ref;
end
end
为了验证这一点,让我们生成一些随机数据并比较
A
和上面代码的输出:clear
N = 1e3; % number of realizations
S = 1e5; % maximum input size
for n = 1:N;
% Generate inputs:
s = randi(S); % input size
A = (2*rand(1,S)-1) / rand; % random input of length S; positive and
% negative values; random scaling
tol = .1*rand; % random tolerance (relative). Change value .1 as desired
% Compute output:
tol_scaled = tol*max(abs(A(:))); % scale tolerance
C = []; % initiallize output. Will be extended
ref = NaN; % initiallize reference value to NaN. This will immediately cause
% A(1) to become the new reference
for a = sort(A(:)).';
if ~(a-ref <= tol_scaled)
ref = a;
C(end+1) = ref;
end
end
% Check if output is equal to that of uniquetol:
assert(isequal(C, uniquetol(A, tol)))
end
在我所有的测试中,这个断言都没有失败。
因此,总而言之,
C
似乎对输入进行排序,选择其第一个条目,并尽可能长时间地跳过条目。对于问题中的两个示例,输出如下注意,第二个输入被指定为
A
,其中uniquetol
是第一个输入的最大值,以达到uniquetol
的绝对容忍度:>> uniquetol([1 3 5 7 9], 2.5/9)
ans =
1 5 9
>> uniquetol([3 5 7 9], 2.5/9)
ans =
3 7