以下是寻找整数因子的六种不同实现方法的比较:
function [t,v] = testFactors()
n = 2*2*2*2*3*3*3*5*5*7*11*13*17*19;
fcns = {
@() factors1(n);
@() factors2(n);
@() factors3(n);
@() factors4(n);
@() factors6(n);
};
t = cellfun(@timeit, fcns);
v = cellfun(@feval, fcns, 'UniformOutput',false);
assert(isequal(v{:}));
end
function f = factors1(n)
f = find(rem(n, 1:floor(sqrt(n))) == 0);
f = unique([1, n, f, fix(n./f)]);
end
function f = factors2(n)
f = [1, n];
for k=2:floor(sqrt(n))
if rem(n,k) == 0
f(end+1) = k;
f(end+1) = fix(n/k);
end
end
f = unique(f);
end
function f = factors3(n)
pf = factor(n);
f = arrayfun(@(k) prod(nchoosek(pf,k),2), 2:numel(pf), ...
'UniformOutput',false);
f = unique([1; pf(:); vertcat(f{:})])';
end
function f = factors4(n)
pf = factor(n);
K = dec2bin(0:2^length(pf)-1)-'0';
f = ones(1,2^length(pf));
for k=1:size(K)
f(k) = prod(pf(~K(k,:)));
end;
f = unique(f);
end
function f = factors5(n)
f = find(rem(n, 1:n) == 0);
end
function f = factors6(n)
f = double(evalin(symengine, sprintf('numlib::divisors(%d)',n)));
end
结果如下:
>> [t,v] = testFactors();
>> t
t =
0.0019
0.0055
0.0102
0.0756
0.1314
>> numel(v{1})
ans =
1920
尽管第一个矢量化版本是最快的,但由于自动JIT优化,等效的基于循环的实现(factors2)也不落后太多。
请注意,我必须禁用暴力实现(factors5()),因为它会抛出内存不足错误(将1:3491888400存储为双精度需要超过26GB的内存!)。 对于大整数,无论从空间还是时间上来看,这种方法显然都不可行。
结论:请使用以下矢量化实现 :)
n = 3491888400;
f = find(rem(n, 1:floor(sqrt(n))) == 0);
f = unique([1, n, f, fix(n./f)]);