【问题标题】:Fast way to test whether n^2 + (n+1)^2 is perfect square测试 n^2 + (n+1)^2 是否为完美平方的快速方法
【发布时间】:2013-05-15 07:44:53
【问题描述】:

我正在尝试编写代码来测试n^2 + (n+1)^2 是否完美。 由于我在编程方面没有太多经验,所以我只能使用 Matlab。 到目前为止,这是我尝试过的

function [ Liste ] = testSquare(N)

        if exist('NumberTheory')
           load NumberTheory.mat
        else
            MaxT = 0;
        end

        if MaxT > N 
            return
        elseif MaxT > 0 
            L = 1 + MaxT;
        else
            L = 1;
        end


    n = (L:N)';            % Makes a list of numbers from L to N
    m = n.^2 + (n+1).^2;   % Makes a list of numbers on the form A^2+(A+1)^2
    P = dec2hex(m);        % Converts this list to hexadecimal 

    Length = length(dec2hex(P(N,:))); %F inds the maximum number of digits in the hexidecimal number
    Modulo = ['0','1','4','9']';      % Only numbers ending on 0,1,4 or 9 can be perfect squares in hex

    [d1,~] = ismember(P(:,Length),Modulo); % Finds all numbers that end on 0,1,4 or 9

    m = m(d1);                             % Removes all numbers not ending on 0,1,4 or 9
    n = n(d1);                             % -------------------||-----------------------
   mm = sqrt(m);                           % Takes the square root of all the possible squares

    A = (floor(mm + 0.5).^2 == m);         % Tests wheter these are actually squares
   lA = length(A(A>0));                    % Finds the number of such numbers

   MaxT = N;
   save NumberTheory.mat MaxT;

if lA>0

    m = m(A);                              % makes a list of all the square numbers
    n = n(A);                              % finds the corresponding n values
   mm = mm(A);                             % Finds the squareroot values of m 

    fid = fopen('Tallteori.txt','wt');     % Writes everything to a simple text.file
        for ii = 1:lA
            fprintf(fid,'%20d %20d %20d\t',n(ii),m(ii),mm(ii));
            fprintf(fid,'\n');
        end
    fclose(fid);

end

end

这会将具有相应 n 值的正方形写入文件。现在我看到使用十六进制是在 C+ 中找到完美正方形的一种快速方法,并尝试在 matlab 中使用它。但是我有点不确定这是否是最好的方法。

上面的代码在m > 2^52 时由于十六进制转换而崩溃。

是否有另一种方法/更快地将表单 n^2 + (n+1)^2 上的所有完美正方形写入从 1 到 N 的文本文件?

【问题讨论】:

    标签: matlab performance perfect-square


    【解决方案1】:

    有一种更快的方法,甚至不需要测试。您需要一些基本数论才能找到这种方法,但这里是:

    如果n² + (n+1)² 是一个完美的正方形,这意味着有一个m 使得

         m² = n² + (n+1)² = 2n² + 2n + 1
    <=> 2m² = 4n² + 4n + 1 + 1
    <=> 2m² = (2n+1)² + 1
    <=> (2n+1)² - 2m² = -1
    

    这种类型的方程很容易求解,从“最小”(正)解开始

    1² - 2*1² = -1
    

    x² - 2y² = -1
    

    对应于数字1 + √2,您可以通过将其乘以原始解的幂来获得所有进一步的解

    a² - 2b² = 1
    

    这是(1 + √2)² = 3 + 2*√2

    写成矩阵形式,得到x² - 2y² = -1的所有解

    |x_k|   |3 4|^k   |1|
    |y_k| = |2 3|   * |1|
    

    并且所有x_k都必然是奇数,因此可以写成2*n + 1

    前几个解决方案(x,y)

    (1,1), (7,5), (41,29), (239,169)
    

    对应(n,m)

    (0,1), (3,5), (20,29), (119,169)
    

    您可以通过以下方式获得下一个(n,m) 解决方案对

    (n_(k+1), m_(k+1)) = (3*n_k + 2*m_k + 1, 4*n_k + 3*m_k + 2)
    

    (n_0, m_0) = (0,1)开始。

    快速 Haskell 代码,因为我不会说 MatLab:

    Prelude> let next (n,m) = (3*n + 2*m + 1, 4*n + 3*m + 2) in take 20 $ iterate next (0,1)
    [(0,1),(3,5),(20,29),(119,169),(696,985),(4059,5741),(23660,33461),(137903,195025)
    ,(803760,1136689),(4684659,6625109),(27304196,38613965),(159140519,225058681)
    ,(927538920,1311738121),(5406093003,7645370045),(31509019100,44560482149)
    ,(183648021599,259717522849),(1070379110496,1513744654945),(6238626641379,8822750406821)
    ,(36361380737780,51422757785981),(211929657785303,299713796309065)]
    Prelude> map (\(n,m) -> (n^2 + (n+1)^2 - m^2)) it
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    

    由 EitanT 编辑

    这是计算第一个 N 数字的 MATLAB 代码:

    res = zeros(1, N);
    nm = [0, 1];
    for k = 1:N
        nm = nm * [3 4; 2 3] + [1, 2];
        res(k) = nm(1);
    end
    

    生成的数组res 应该包含满足完美正方形条件的n 的值。

    【讨论】:

    • +1:我冒昧地将 MATLAB 代码添加到您的答案中。
    • 谢谢。我能理解,但我写不出来;)
    猜你喜欢
    • 1970-01-01
    • 2011-01-29
    • 2011-05-23
    • 1970-01-01
    • 2017-12-23
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多