输入一个整数,找到两个最接近的整数,当乘以时,等于输入

时间:2013-04-28 19:35:04

标签: arrays math matrix data-conversion

好的,我的问题属于数学性质。 我有一个长度为X的字节数组,我需要找到两个最接近的数字,它们相乘在一起等于X. 我需要这样做,因为我正在从一个字节数组中构建一个位图,我需要尽可能使位图看起来像一个正方形。 我在C#中对此进行编码,但不要担心语法,任何算法或伪代码都可以。 在此先感谢您的帮助

7 个答案:

答案 0 :(得分:10)

对于这个问题,可能有一个更好的算法,但最重要的是:

1) Take the square root of the number X; we'll call it N.
2) Set N equal to the ceiling of N (round up to the nearest integer).
3) Test for (X % N). If N divides evenly into X, we found our first number.
  if 0, divide X by N to get M. M and N are our numbers
  if not 0, increment N by 1 and start step 3 over.

答案 1 :(得分:4)

我已经用user85109在一个详细的函数中重写了上面提出的MATLAB答案,其中有足够的注释和一些更简单的术语。当然非常有效,适用于大量数据,并且希望能够以任何语言轻松编写,该语言提供了用于获得整数的素数因子化的库函数。

        function [a, b] =  findIntegerFactorsCloseToSquarRoot(n)
        % a cannot be greater than the square root of n
        % b cannot be smaller than the square root of n
        % we get the maximum allowed value of a
        amax = floor(sqrt(n));
        if 0 == rem(n, amax)
            % special case where n is a square number
            a = amax;
            b = n / a;
            return;
        end
        % Get its prime factors of n
        primeFactors  = factor(n);
        % Start with a factor 1 in the list of candidates for a
        candidates = [1];
        for i=1:numel(primeFactors)
            % get the next prime factr
            f = primeFactors(i);
            % Add new candidates which are obtained by multiplying
            % existing candidates with the new prime factor f
            % Set union ensures that duplicate candidates are removed
            candidates  = union(candidates, f .* candidates);
            % throw out candidates which are larger than amax
            candidates(candidates > amax) = [];
        end
        % Take the largest factor in the list d
        a = candidates(end);
        b = n / a;
    end

答案 2 :(得分:3)

请注意,如果X非常大,那么从sqrt(X)开始并一次向下工作一步将是一项悲惨的任务。这可能需要很长时间。

如果你能找到数字的因子,那么只需计算X的所有除数小于sqrt(X)。

考虑数字X = 123456789012345678901234567890。小于sqrt(X)的最小整数是351364182882014,因此简单地递减该值以测试除数可能会有问题。

保理X,我们得到这个主要因素列表:

{2, 3, 3, 3, 5, 7, 13, 31, 37, 211, 241, 2161, 3607, 3803, 2906161}

计算除数小于sqrt(N)是一个相当快的运算,给出了素数因子,得到除数349788919693221,所以我们有

349788919693221 * 352946540218090 = 123456789012345678901234567890

这些是N数最接近的除数。但是,从sqrt(N)开始,我们需要减少多少次?这个区别是:1575263188793,所以超过1.5e12步。

确定指示因子的简单方案(在MATLAB中)

Dmax = 351364182882014;
F = [2, 3, 3, 3, 5, 7, 13, 31, 37, 211, 241, 2161, 3607, 3803, 2906161];
D = 1;
for i = 1:numel(F)
  D = kron(D,[1,F(i)]);
  D = unique(D);
  D(D > Dmax) = [];
end

D(end)
ans =
     349788919693221

另一个因素就足够了。如果数字太大而不能超过燧石的动态范围,那么你需要使用一些更高精度算术的变体。

答案 3 :(得分:1)

一个完美的正方形将有一个SQRT(X)的一面,所以从那里开始向下工作。

int X = ...
for(int i=sqrt(x);i>0;i--) {
  // integer division discarding remainder:
  int j = X/i;
  if( j*i == X ) {
    // closest pair is (i,j)
    return (i,j);
  }
}
return NULL;

请注意,只有X实际上可被两个整数整除时才会起作用(即素数X最终会以(1,X)结束)。根据你正在做的事情,你可能最好选择稍大一些的尺寸,然后使它成正方形......即边长为CEILING(SQRT(X))

答案 4 :(得分:0)

另一种方法是设置此优化问题

最小化因子X和Y的差异 产品X×Y和P的差异因此,你有一个目标函数加权了两个目标:

       min c × |X × Y - P|  +  d × |X – Y|
subject to X, Y ∈ ℤ
           X, Y ≥ 0

其中c,d是非负数,用于定义您估算的目标值。

然而,与sqrt解决方案很相似:)

答案 5 :(得分:0)

感谢您的回答。我已经创建了一个函数,可以在sqrt方法中找到最接近的3个整数:

function [a, b, c] =  findIntegerFactorsCloseToCubeRoot(n)
% a cannot be greater than the cube root of n
% b cannot be smaller than the cube root of n
% we get the maximum allowed value of a
amax = floor(nthroot(n,3))
if amax^3 == n
    % special case where n is a cube number
    a = amax;
    b = a;
    c = a;
    return;
end
% Get its prime factors of n
primeFactors  = factor(n);
% Start with a factor 1 in the list of candidates for a
candidates = [1];
for i=1:numel(primeFactors)
    % get the next prime factor
    f = primeFactors(i);
    % Add new candidates which are obtained by multiplying
    % existing candidates with the new prime factor f
    % Set union ensures that duplicate candidates are removed
    candidates  = union(candidates, f .* candidates);
    % throw out candidates which are larger than amax
    candidates(candidates > amax) = [];
end
% Take the largest factor in the list d
a = candidates(end);
% call similar function for remaining 2 factors
[b, c] = findIntegerFactorsCloseToSqRoot(n/a);
end

答案 6 :(得分:0)

我还不允许发表评论,所以这里是一个基于@Anthony DeSimone 的答案的快速 python>=3.8 实现,修改为使用 @Egor Skriptunoff 建议的 floor():

import math
def sqrt_int(X: int):
    N = math.floor(math.sqrt(X))
    while bool(X % N):
        N -= 1
    M = X // N
    return M, N