C# 将一个数分解为2个素数辅因子

C# 将一个数分解为2个素数辅因子,c#,primes,factors,telegram,C#,Primes,Factors,Telegram,其要求之一是将给定的数字分解为2个素数辅因子。特别是P*Q=N,其中N

其要求之一是将给定的数字分解为2个素数辅因子。特别是
P*Q=N,其中N<2^63

我们怎样才能找到更小的素数余因子,比如
p

我的建议是:

1) 将素数从3预先计算到
2^31.5
,然后测试
N mod p=0

2) 找到一个算法来测试素数(但我们仍然需要测试
N mod p=0


有适合这种情况的素数算法吗!我刚把这个程序放进去,然后意识到你把你的问题标记为C。这是C++,一个版本的波拉德Rho我写了几年前,张贴在这里,以便帮助其他人理解它。它分解半素数的速度比试除法快很多倍。正如我所说的,我很遗憾,它是C++而不是C语言,但是你应该能够理解这个概念,甚至很容易理解它。作为一个额外的补充,.NET库有一个命名空间来处理任意大的整数,其中我的C++实现需要我去为它们找到第三方库。无论如何,即使在C#中,下面的程序也会在不到1秒的时间内将一个2^63阶半素数分解为2个素数。甚至还有比这更快的算法,但它们要复杂得多

#include <string>
#include <stdio.h>
#include <iostream>
#include "BigIntegerLibrary.hh"

typedef BigInteger BI;
typedef BigUnsigned BU;

using std::string;
using std::cin;
using std::cout;

BU pollard(BU &numberToFactor);
BU gcda(BU differenceBetweenCongruentFunctions, BU numberToFactor);
BU f(BU &x, BU &numberToFactor, int &increment);
void initializeArrays();
BU getNumberToFactor ();
void factorComposites();
bool testForComposite (BU &num);

BU primeFactors[1000];
BU compositeFactors[1000];
BU tempFactors [1000];
int primeIndex;
int compositeIndex;
int tempIndex;
int numberOfCompositeFactors;
bool allJTestsShowComposite;

int main ()
{
    while(1)
    {
        primeIndex=0;
        compositeIndex=0;
        tempIndex=0;
        initializeArrays();
        compositeFactors[0] = getNumberToFactor();
        cout<<"\n\n";
        if (compositeFactors[0] == 0) return 0;
        numberOfCompositeFactors = 1;
        factorComposites();
    }
}

void initializeArrays()
{
    for (int i = 0; i<1000;i++)
    {
        primeFactors[i] = 0;
        compositeFactors[i]=0;
        tempFactors[i]=0;
    }
}

BU getNumberToFactor ()
{
    std::string s;
    std::cout<<"Enter the number for which you want a prime factor, or 0 to     quit: ";
    std::cin>>s;
    return stringToBigUnsigned(s);
}

void factorComposites()
{
    while (numberOfCompositeFactors!=0)
    {
        compositeIndex = 0;
        tempIndex = 0;

        // This while loop finds non-zero values in compositeFactors.
        // If they are composite, it factors them and puts one factor in     tempFactors,
        // then divides the element in compositeFactors by the same amount.
        // If the element is prime, it moves it into tempFactors (zeros the     element in compositeFactors)
        while (compositeIndex < 1000)
        {
            if(compositeFactors[compositeIndex] == 0)
            {
                compositeIndex++;
                continue;
            }
            if(testForComposite(compositeFactors[compositeIndex]) == false)
            {
                tempFactors[tempIndex] = compositeFactors[compositeIndex];
                compositeFactors[compositeIndex] = 0;
                tempIndex++;
                compositeIndex++;
            }
            else
            {
                tempFactors[tempIndex] = pollard     (compositeFactors[compositeIndex]);
                compositeFactors[compositeIndex] /= tempFactors[tempIndex];
                tempIndex++;
                compositeIndex++;
            }
        }
        compositeIndex = 0;

        // This while loop moves all remaining non-zero values from     compositeFactors into tempFactors
        // When it is done, compositeFactors should be all 0 value elements
        while (compositeIndex < 1000)
        {
            if (compositeFactors[compositeIndex] != 0)
            {
                tempFactors[tempIndex] = compositeFactors[compositeIndex];
                compositeFactors[compositeIndex] = 0;
                tempIndex++;
                compositeIndex++;
            }
            else compositeIndex++;
        }
        compositeIndex = 0;
        tempIndex = 0;
    // This while loop checks all non-zero elements in tempIndex.
    // Those that are prime are shown on screen and moved to primeFactors
    // Those that are composite are moved to compositeFactors
    // When this is done, all elements in tempFactors should be 0
    while (tempIndex<1000)
    {
        if(tempFactors[tempIndex] == 0)
        {
            tempIndex++;
            continue;
        }
        if(testForComposite(tempFactors[tempIndex]) == false)
        {
            primeFactors[primeIndex] = tempFactors[tempIndex];
            cout<<primeFactors[primeIndex]<<"\n";
            tempFactors[tempIndex]=0;
            primeIndex++;
            tempIndex++;
        }
        else
        {
            compositeFactors[compositeIndex] = tempFactors[tempIndex];
            tempFactors[tempIndex]=0;
            compositeIndex++;
            tempIndex++;
        }
    }
    compositeIndex=0;
    numberOfCompositeFactors=0;

    // This while loop just checks to be sure there are still one or more composite factors.
    // As long as there are, the outer while loop will repeat
    while(compositeIndex<1000)
    {
        if(compositeFactors[compositeIndex]!=0) numberOfCompositeFactors++;
        compositeIndex ++;
    }
}
return;
}

// The following method uses the Miller-Rabin primality test to prove with 100% confidence a given number is composite,
// or to establish with a high level of confidence -- but not 100% -- that it is prime

bool testForComposite (BU &num)
{
    BU confidenceFactor = 101;
    if (confidenceFactor >= num) confidenceFactor = num-1;
    BU a,d,s, nMinusOne;
    nMinusOne=num-1;
    d=nMinusOne;
    s=0;
    while(modexp(d,1,2)==0)
    {
        d /= 2;
        s++;
    }
    allJTestsShowComposite = true; // assume composite here until we can prove otherwise
    for (BI i = 2 ; i<=confidenceFactor;i++)
    {
        if (modexp(i,d,num) == 1) 
            continue;  // if this modulus is 1, then we cannot prove that num is composite with this value of i, so continue
        if (modexp(i,d,num) == nMinusOne)
        {
            allJTestsShowComposite = false;
            continue;
        }
        BU exponent(1);     
        for (BU j(0); j.toInt()<=s.toInt()-1;j++)
        {
            exponent *= 2;
            if (modexp(i,exponent*d,num) == nMinusOne)
            {
                // if the modulus is not right for even a single j, then break and increment i.
                allJTestsShowComposite = false;
                continue;
            }
        }
        if (allJTestsShowComposite == true) return true; // proven composite with 100% certainty, no need to continue testing
    }
    return false;
    /* not proven composite in any test, so assume prime with a possibility of error = 
    (1/4)^(number of different values of i tested).  This will be equal to the value of the
confidenceFactor variable, and the "witnesses" to the primality of the number being tested will be all integers from
2 through the value of confidenceFactor.

Note that this makes this primality test cryptographically less secure than it could be.  It is theoretically possible,
if difficult, for a malicious party to pass a known composite number for which all of the lowest n integers fail to
detect that it is composite.  A safer way is to generate random integers in the outer "for" loop and use those in place of
the variable i.  Better still if those random numbers are checked to ensure no duplicates are generated.
*/
}

BU pollard(BU &n)
{
    if (n == 4) return 2;
    BU x = 2;
    BU y = 2;
    BU d = 1;
    int increment = 1;

    while(d==1||d==n||d==0)
    {
        x = f(x,n, increment);
        y = f(y,n, increment);
        y = f(y,n, increment);
        if (y>x)
        {
            d = gcda(y-x, n);
        }
        else
        {
            d = gcda(x-y, n);
        }
        if (d==0) 
        {
            x = 2;
            y = 2;
            d = 1;
            increment++; // This changes the pseudorandom function we use to increment x and y
        }
    }
    return d;
}


BU gcda(BU a, BU b)
{
    if (a==b||a==0)
        return 0;   // If x==y or if the absolute value of (x-y) == the number to be factored, then we have failed to find
                    // a factor.  I think this is not proof of primality, so the process could be repeated with a new function.
                    // For example, by replacing x*x+1 with x*x+2, and so on.  If many such functions fail, primality is likely.

    BU currentGCD = 1;
    while (currentGCD!=0) // This while loop is based on Euclid's algorithm
    {
        currentGCD = b % a;
        b=a;
        a=currentGCD;
    }
    return b;
}

BU f(BU &x, BU &n, int &increment)
{
    return (x * x + increment) % n;
}
#包括
#包括
#包括
#包括“BigIntegerLibrary.hh”
typedef-biginger-BI;
typedef big无符号BU;
使用std::string;
使用std::cin;
使用std::cout;
BU pollard(BU和numberToFactor);
BU gcda(协调函数之间的BU差异,BU数量因子);
BU f(BU&x、BU&numberToFactor、int&increment);
void initializeArrays();
bugetnumbertofactor();
孔隙系数复合物();
复合材料的布尔测试(BU和num);
因子[1000];
BU合成因子[1000];
BU系数[1000];
整数素数索引;
综合指数;
int临时索引;
整数复合因子;
bool-alljtestsshowscomposite;
int main()
{
而(1)
{
primeIndex=0;
复合指数=0;
tempIndex=0;
初始化arrays();
compositeFactors[0]=getNumberToFactor();

coutPollard的Rho算法[VB.Net]

对于
N<2^63

Dim rnd As New System.Random

Function PollardRho(n As BigInteger) As BigInteger
    If n Mod 2 = 0 Then Return 2

    Dim x As BigInteger = rnd.Next(1, 1000)
    Dim c As BigInteger = rnd.Next(1, 1000)
    Dim g As BigInteger = 1
    Dim y = x

    While g = 1
        x = ((x * x) Mod n + c) Mod n
        y = ((y * y) Mod n + c) Mod n
        y = ((y * y) Mod n + c) Mod n
        g = gcd(BigInteger.Abs(x - y), n)
    End While

    Return g
End Function

Function gcd(a As BigInteger, b As BigInteger) As BigInteger
    Dim r As BigInteger
    While b <> 0
        r = a Mod b
        a = b
        b = r
    End While
    Return a
End Function
Dim rnd作为新系统。随机
函数PollardRho(n作为biginger)作为biginger
如果n Mod 2=0,则返回2
Dim x作为biginger=rnd.Next(11000)
Dim c作为biginger=rnd.Next(11000)
Dim g作为BigInteger=1
尺寸y=x
而g=1
x=((x*x)模n+c)模n
y=((y*y)模n+c)模n
y=((y*y)模n+c)模n
g=gcd(biginger.Abs(x-y),n)
结束时
返回g
端函数
函数gcd(a作为BigInteger,b作为BigInteger)作为BigInteger
Dim r作为biginger
而b0
r=a模b
a=b
b=r
结束时
归还
端函数
Richard Brent的算法[VB.Net]这甚至更快

Function Brent(n As BigInteger) As BigInteger
    If n Mod 2 = 0 Then Return 2

    Dim y As BigInteger = rnd.Next(1, 1000)
    Dim c As BigInteger = rnd.Next(1, 1000)
    Dim m As BigInteger = rnd.Next(1, 1000)

    Dim g As BigInteger = 1
    Dim r As BigInteger = 1
    Dim q As BigInteger = 1

    Dim x As BigInteger = 0
    Dim ys As BigInteger = 0

    While g = 1
        x = y
        For i = 1 To r
            y = ((y * y) Mod n + c) Mod n
        Next
        Dim k = New BigInteger(0)
        While (k < r And g = 1)
            ys = y
            For i = 1 To BigInteger.Min(m, r - k)
                y = ((y * y) Mod n + c) Mod n
                q = q * (BigInteger.Abs(x - y)) Mod n
            Next

            g = gcd(q, n)
            k = k + m
        End While
        r = r * 2
    End While

    If g = n Then
        While True
            ys = ((ys * ys) Mod n + c) Mod n
            g = gcd(BigInteger.Abs(x - ys), n)
            If g > 1 Then
                Exit While
            End If
        End While
    End If

    Return g
End Function
函数Brent(n作为biginger)作为biginger
如果n Mod 2=0,则返回2
Dim y作为biginger=rnd.Next(11000)
Dim c作为biginger=rnd.Next(11000)
Dim作为biginger=rnd.Next(11000)
Dim g作为BigInteger=1
Dim r为BigInteger=1
Dim q为BigInteger=1
尺寸x为BigInteger=0
Dim ys作为BigInteger=0
而g=1
x=y
对于i=1到r
y=((y*y)模n+c)模n
下一个
Dim k=新的大整数(0)
而(k1,则
退出时
如果结束
结束时
如果结束
返回g
端函数

你确定这是一项要求吗?他们描述的整个东西在某种意义上看起来像RSA,但有玩具长度密钥。在真正的RSA中,pq这么长很重要,没有公开的算法可以在合理的时间内对其进行因子分解。但是,如果你真的想对小于2^63的半素数进行因子分解(因此,在18位数的范围内)Pollard Rho在C++中可以在几天内在PC上完成它。这里有Purrad Rho的列表。特殊的数字字段筛选器可以在几秒钟内完成。而且它太小,甚至不能使用GNF。请检查M筛选器。它应该引起您的兴趣。@ WDS是一个要求。我甚至连到了API页的一部分。@ WD,我想您不是RIGH。就时间要求而言,t。我们已经得到了N。我们所需要做的就是将它分解成2个素数。我已经用我的vb.net代码在4分钟内用蛮力完成了这项工作。我只是希望得到一些帮助,将这项工作减少到几秒钟或更短。哦,非常抱歉,关于时间要求,你是对的。我正在做我的估算根据我自己对Pollard Rho的经验,以及对2^63范围内的一个数字的一般估计,大约18位长。这是正确的。我记得我的Pollard Rho用了几秒钟,例如12位数字。但我记错了一个关键事实。这几秒钟是用来计算基本因子为12位时的,不是在产品是12位的时候。我的程序会在眨眼之间将一个半素数的18位数字进行因子运算。我会为您发布。@CharlesO,GNU因子代码是Neil和Torbjörn的NT项目。自含,无GMP,128位。我的本机代码是可以独立编译的代码(见factor.c末尾),GMP代码为。我的一个待办项目是将其全部转换为常规C库。顺便说一句,我不知道这是否是公认的做法,但这里有一个