首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >整数因式分解

整数因式分解
EN

Stack Overflow用户
提问于 2014-01-09 18:49:07
回答 3查看 4.4K关注 0票数 10

在回答另一个问题时,我无意中发现了一个问题,即如何在没有符号数学工具箱()的情况下找到整数的所有因素。

例如:

代码语言:javascript
复制
factor(60)

返回:

代码语言:javascript
复制
 2     2     3     5

代码语言:javascript
复制
unique(factor(60))

因此将返回所有素因子,"1"缺失。

代码语言:javascript
复制
 2     3     5

我正在寻找一个函数,它将返回所有因素(1数字本身并不重要,但它们会很好)

x = 60**:**的预期输出

代码语言:javascript
复制
 1     2     3     4     5     6    10    12    15    20    30    60     

我想出了一个相当庞大的解决方案,除此之外,它很可能是矢量化的,难道没有任何优雅的解决方案吗?

代码语言:javascript
复制
x = 60;

P = perms(factor(x));
[n,m] = size(P);
Q = zeros(n,m);
for ii = 1:n
    for jj = 1:m
        Q(ii,jj) = prod(P(ii,1:jj));
    end
end

factors = unique(Q(:))'

而且我认为,对于某些大的数字,这个解决方案将失败,因为perms需要一个向量长度< 11。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-01-10 14:50:32

下面是查找整数因子的六种不同实现的比较:

代码语言:javascript
复制
function [t,v] = testFactors()
    % integer to factor
    %{45, 60, 2059, 3135, 223092870, 3491888400};
    n = 2*2*2*2*3*3*3*5*5*7*11*13*17*19;

    % functions to compare
    fcns = {
        @() factors1(n);
        @() factors2(n);
        @() factors3(n);
        @() factors4(n);
        %@() factors5(n);
        @() factors6(n);
    };

    % timeit
    t = cellfun(@timeit, fcns);

    % check results
    v = cellfun(@feval, fcns, 'UniformOutput',false);
    assert(isequal(v{:}));
end

function f = factors1(n)
    % vectorized implementation of factors2()
    f = find(rem(n, 1:floor(sqrt(n))) == 0);
    f = unique([1, n, f, fix(n./f)]);
end

function f = factors2(n)
    % factors come in pairs, the smaller of which is no bigger than sqrt(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)
    % Get prime factors, and compute products of all possible subsets of size>1
    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)
    % http://rosettacode.org/wiki/Factors_of_an_integer#MATLAB_.2F_Octave
    pf = factor(n);                    % prime decomposition
    K = dec2bin(0:2^length(pf)-1)-'0'; % all possible permutations
    f = ones(1,2^length(pf));
    for k=1:size(K)
      f(k) = prod(pf(~K(k,:)));        % compute products 
    end; 
    f = unique(f);                     % eliminate duplicates
end

function f = factors5(n)
    % @LuisMendo: brute-force implementation
    f = find(rem(n, 1:n) == 0);
end

function f = factors6(n)
    % Symbolic Math Toolbox
    f = double(evalin(symengine, sprintf('numlib::divisors(%d)',n)));
end

结果:

代码语言:javascript
复制
>> [t,v] = testFactors();
>> t
t =
    0.0019        % factors1()
    0.0055        % factors2()
    0.0102        % factors3()
    0.0756        % factors4()
    0.1314        % factors6()

>> numel(v{1})
ans =
        1920

尽管第一个矢量化版本是最快的,但是由于自动的JIT优化,等效的基于循环的实现(factors2)也不远了。

注意,我必须禁用蛮力实现(factors5()),因为它会抛出内存不足的错误(以双精度存储向量1:3491888400需要超过26 in的内存!)。这种方法显然不适用于大整数,无论是空间上还是时间上。

结论:使用以下矢量化实现:)

代码语言:javascript
复制
n = 3491888400;
f = find(rem(n, 1:floor(sqrt(n))) == 0);
f = unique([1, n, f, fix(n./f)]);
票数 11
EN

Stack Overflow用户

发布于 2014-01-09 19:11:52

可以通过将一个数字n除以包含整数1到n的向量来找出它的所有因素,然后求出除以1后的余数正好为零(即整数结果):

代码语言:javascript
复制
>> n = 60;
>> find(rem(n./(1:n), 1) == 0)

ans =

     1     2     3     4     5     6    10    12    15    20    30    60
票数 13
EN

Stack Overflow用户

发布于 2014-01-09 20:27:42

@gnovice's answer相比,一个改进是跳过除法操作:仅rem就足够了:

代码语言:javascript
复制
n = 60;
find(rem(n, 1:n)==0)
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21028646

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档