Java 整数分解问题

Java 整数分解问题,java,Java,有人能给我解释一下为什么下面的算法是一种无错误的整数分解方法,它总是返回一个非平凡因子N。 我知道这听起来有多奇怪,但我两年前设计了这个方法,但仍然不理解它背后的数学逻辑,这使得我很难改进它。它非常简单,只涉及加法和减法 public static long factorX( long N ) { long x=0, y=0; long b = (long)(Math.sqrt(N)); long a = b*(b+1)-N; if( a==b ) return

有人能给我解释一下为什么下面的算法是一种无错误的整数分解方法,它总是返回一个非平凡因子N。 我知道这听起来有多奇怪,但我两年前设计了这个方法,但仍然不理解它背后的数学逻辑,这使得我很难改进它。它非常简单,只涉及加法和减法

public static long factorX( long N )
{
    long x=0, y=0;
    long b = (long)(Math.sqrt(N));
    long a = b*(b+1)-N;
    if( a==b ) return a;

    while ( a!= 0 )
    {
        a-= ( 2+2*x++ - y);
        if( a<0 ) { a+= (x+b+1); y++; }
    }

return ( x+b+1 );
}
重写方法:

public static long factorX(long N)
{
long x=1, y=0, f=1;
long b = (long)(Math.sqrt(N));
long a = b*(b+1)-N;
if( a==b ) return a;

  while( f != 0 )
  {
    f = a - x*(x+1) + (x+b+1)*y;
      if( f < 0 ) y++;
    x++;
  }

return x+b+1;
}  

好的,我用Matlab来看看这里发生了什么。以下是N=100000的结果: 在每次迭代中,您都在增加
x
,而
a
变量的有趣模式与剩余的
N%x+b+1
(如图中的灰色线所示,
a+(N%(x+b+1))-x=floor(sqrt(N))
)。 因此,我认为你只是通过简单的迭代找到了比
sqrt(N)
更大的第一个因子,但是有一个相当模糊的标准来决定它是否真的是一个因子:D (很抱歉回答了一半…我得走了,我以后可能会继续)

以下是matlab代码,以防您希望自己进行测试:

clear all
close all

N = int64(100000);

histx = [];
histDiffA = [];
histy = [];
hista = [];
histMod = [];
histb = [];

x=int64(0);
y=int64(0);
b = int64(floor(sqrt(double(N))));
a = int64(b*(b+1)-N);
if( a==b ) 
    factor = a;
else
    while ( a ~= 0 )
        a = a - ( 2+2*x - y);
        histDiffA(end+1) = ( 2+2*x - y);
        x = x+1;
        if( a<0 ) 
            a = a + (x+b+1); 
            y = y+1;
        end
        hista(end+1) = a;
        histb(end+1) = b;
        histx(end+1) = x;
        histy(end+1) = y;
        histMod(end+1) = mod(N,(x+b+1));
    end
    factor = x+b+1;
end

figure('Name', 'Values');
hold on
    plot(hista,'-or')
    plot(hista+histMod-histx,'--*', 'Color', [0.7 0.7 0.7])
    plot(histb,'-ob')
    plot(histx,'-*g')
    plot(histy,'-*y')
    legend({'a', 'a+mod(N,x+b+1)-x', 'b', 'x', 'y'}); % 'Input',
hold off

fprintf( 'factor is %d \n', factor );
全部清除
全部关闭
N=int64(100000);
histx=[];
histDiffA=[];
历史=[];
hista=[];
histMod=[];
histb=[];
x=int64(0);
y=int64(0);
b=int64(楼层(二层(N));
a=int64(b*(b+1)-N);
如果(a==b)
系数=a;
其他的
while(a~=0)
a=a-(2+2*x-y);
histDiffA(end+1)=(2+2*x-y);
x=x+1;

如果(a你的方法是(n-a)*(n+b)的试乘的变体,其中n=下限(sqrt(n))和b==1

然后,该算法迭代a--/b++直到(n-a)*(n+b)-n==0的差

部分差异(关于a和b)分别与2b和2a成比例。因此不需要真正的乘法

复杂度是| a |或| b |的线性函数--“平方”N越多,方法收敛速度越快。总之,有更快的方法,最容易理解的方法之一是二次剩余筛。

请原谅我的c,我不懂Java。 将x和y步进2可提高算法速度

使用System.Numerics;//BigInteger需要
/*方法************************************************************/
私有静态BigInteger sfactor(BigInteger k)//因子奇数整数
{
大整数x,y;
int标志;
x=y=iSqrt(k);//整数平方根
如果(x%2==0){x-=1;y+=1;}//如果偶数使x&y为奇数
做
{ 
flag=BigInteger.Compare((x*y),k);
如果(标志>0)x-=2;
y+=2;
}while(flag!=0);
返回x;//返回x
}//sfactor()的结尾
//查找正数的整数平方根
私有静态BigInteger iSqrt(BigInteger num)
{
如果(0==num){return 0;}//避免零除
BigInteger n=(num/2)+1;//初始估计,从不低
BigInteger n1=(n+(num/n))>>1;//右移以除以2
而(n1>1;//右移以除以2
}
返回n;

}//end iSqrt()
我假设N是方法的参数,而不是y?重复的局部变量y将y更改为N(是的,N是参数,对此很抱歉)你还应该修正
a
b
变量声明:它应该是
long b…
long a…。
我想。编辑:声明的a和b感谢你的努力。我也认为该方法发现第一个因子大于sqrt(N).我仍然需要对a的行为有更多的了解。考虑到基本操作非常便宜,可以做些什么来减少迭代次数。
349752871155505651 = 666524689 x 524741059   in 322 ms
259160452058194903 = 598230151 x 433211953   in 404 ms
339850094323758691 = 764567807 x 444499613   in 1037 ms
244246972999490723 = 606170657 x 402934339   in 560 ms
285622950750261931 = 576888113 x 495109787   in 174 ms
191975635567268981 = 463688299 x 414018719   in 101 ms
207216185150553571 = 628978741 x 329448631   in 1029 ms
224869951114090657 = 675730721 x 332780417   in 1165 ms
315886983148626037 = 590221057 x 535201141   in 110 ms
810807767237895131 = 957028363 x 847213937   in 226 ms
469066333624309021 = 863917189 x 542952889   in 914 ms
clear all
close all

N = int64(100000);

histx = [];
histDiffA = [];
histy = [];
hista = [];
histMod = [];
histb = [];

x=int64(0);
y=int64(0);
b = int64(floor(sqrt(double(N))));
a = int64(b*(b+1)-N);
if( a==b ) 
    factor = a;
else
    while ( a ~= 0 )
        a = a - ( 2+2*x - y);
        histDiffA(end+1) = ( 2+2*x - y);
        x = x+1;
        if( a<0 ) 
            a = a + (x+b+1); 
            y = y+1;
        end
        hista(end+1) = a;
        histb(end+1) = b;
        histx(end+1) = x;
        histy(end+1) = y;
        histMod(end+1) = mod(N,(x+b+1));
    end
    factor = x+b+1;
end

figure('Name', 'Values');
hold on
    plot(hista,'-or')
    plot(hista+histMod-histx,'--*', 'Color', [0.7 0.7 0.7])
    plot(histb,'-ob')
    plot(histx,'-*g')
    plot(histy,'-*y')
    legend({'a', 'a+mod(N,x+b+1)-x', 'b', 'x', 'y'}); % 'Input',
hold off

fprintf( 'factor is %d \n', factor );