⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bigint.cpp

📁 高效率大数运算库源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    for(int i=m_nLength-1;i>=0;i--)
    {
        div=m_ulValue[i];
		div+=carry*0x100000000;
        carry=(unsigned long)(div%A);
    }
    return carry;
}

/****************************************************************************************
大数开方
调用形式:N.Sqr()
返回值:N的算术平方根
****************************************************************************************/
CBigInt CBigInt::Sqrt()
{
    CBigInt X,M,N;
	unsigned long m,n;
	n=m_ulValue[m_nLength-1];
	n=(unsigned long)sqrt((double)n);
	m=n+1;
	if(m_nLength==1){X.Mov(n);return X;}
	N.m_nLength=m_nLength/2;
	M.m_nLength=N.m_nLength;
	if(m_nLength&1)
	{
		M.m_nLength++;
		N.m_nLength++;
		M.m_ulValue[M.m_nLength-1]=m;
		N.m_ulValue[N.m_nLength-1]=n;
	}
	else 
	{
		M.m_ulValue[M.m_nLength-1]=(m<<16);
		N.m_ulValue[N.m_nLength-1]=(n<<16);
	}
	X.Mov(M.Add(N));
	X.Mov(X.Div(2));
	while(1)
	{
		if(Cmp(X.Mul(X))<0)M.Mov(X);
        else N.Mov(X);
		X.Mov(M.Sub(N));
		if((X.m_ulValue[0]==1)&&(X.m_nLength==1))return N;
  	    X.Mov(M.Add(N));
	    X.Mov(X.Div(2));
	}
}

/****************************************************************************************
从字符串按2进制到36进制格式输入到大数
调用格式:N.Get(str,sys)
返回值:N被赋值为相应大数
****************************************************************************************/
void CBigInt::Get(CString& str, unsigned int system)
{
    int len=str.GetLength(),k;
    Mov(0);
    for(int i=0;i<len;i++)
    {
       Mov(Mul(system));
       if((str[i]>='0')&&(str[i]<='9'))k=str[i]-48;
       else if((str[i]>='A')&&(str[i]<='Z'))k=str[i]-55;
       else if((str[i]>='a')&&(str[i]<='z'))k=str[i]-87;
       else k=0;
       Mov(Add(k));
    }
}

/****************************************************************************************
将大数按2进制到36进制格式输出为字符串
调用格式:N.Put(str,sys)
返回值:无,参数str被赋值为N的sys进制字符串
****************************************************************************************/
void CBigInt::Put(CString& str, unsigned int system)
{
    if((m_nLength==1)&&(m_ulValue[0]==0)){str="0";return;}
	str="";
    int a;
    char ch;
    CBigInt X;
    X.Mov(*this);
    while(X.m_ulValue[X.m_nLength-1]>0)
    {
        a=X.Mod(system);
        ch=CharTable[a];
        str.Insert(0,ch);
        X.Mov(X.Div(system));
    }
}

/****************************************************************************************
求模逆,即解同余方程NX%A=1,亦即解不定方程NX-AY=1的最小整数解
调用方式:N.ModInv(A)
返回值:X,满足:NX%A=1
****************************************************************************************/
CBigInt CBigInt::ModInv(CBigInt& A)
{
	CBigInt M,E,X,Y,I,J;
    int x,y;
	M.Mov(A);
	E.Mov(*this);
	X.Mov(0);
	Y.Mov(1);
	x=y=1;
	while((E.m_nLength!=1)||(E.m_ulValue[0]!=0))
	{
		I.Mov(M.Div(E));
		J.Mov(M.Mod(E));
		M.Mov(E);
		E.Mov(J);
		J.Mov(Y);
		Y.Mov(Y.Mul(I));
		if(x==y)
		{
		    if(X.Cmp(Y)>=0)Y.Mov(X.Sub(Y));
			else{Y.Mov(Y.Sub(X));y=0;}
		}
		else{Y.Mov(X.Add(Y));x=1-x;y=1-y;}
		X.Mov(J);
	}
	if(x==0)X.Mov(A.Sub(X));
	return X;
}

/****************************************************************************************
求模乘
调用方式:N.ModMul(A,B)
返回值:X=N*A%B
****************************************************************************************/
CBigInt CBigInt::ModMul(CBigInt& A, CBigInt& B)
{
	int i,j;
	CBigInt X;
	X.Mov(A.Mul(m_ulValue[m_nLength-1]));
	X.Mov(X.Mod(B));
    for(i=m_nLength-2;i>=0;i--)
	{          
		for(j=X.m_nLength;j>0;j--)X.m_ulValue[j]=X.m_ulValue[j-1];
		X.m_ulValue[0]=0;
		X.m_nLength++;
		X.Mov(X.Add(A.Mul(m_ulValue[i])));
		X.Mov(X.Mod(B));
	}
    return X;
}

/****************************************************************************************
求蒙哥马利模乘
调用方式:N.MonPro(A,B,n),(2**(k-1)<B<2**k,R=2**k,R*R'%B=1,n*B[0]%0x100000000=-1) 
返回值:X=N*A*R'%B
****************************************************************************************/
CBigInt CBigInt::MonPro(CBigInt& A, CBigInt& B, unsigned long n)
{
	CBigInt X;
	unsigned long T[BI_MAXLEN*2];
	unsigned i,j,k;
	unsigned long m,carry;
	unsigned __int64 sum;
	for(i=0;i<BI_MAXLEN*2;i++)T[i]=0;
	k=B.m_nLength;
	for(i=0;i<k;i++)
	{
		carry=0;
		for(j=0;j<k;j++)
		{
			sum=A.m_ulValue[i];
			sum=sum*m_ulValue[j]+T[i+j]+carry;
			T[i+j]=(unsigned long)sum;
			carry=(unsigned long)(sum>>32);
		}
		T[i+k]=carry;
	}
	for(i=0;i<k;i++)
	{
		carry=0;
		m=T[i]*n;
		for(j=0;j<k;j++)
		{
			sum=B.m_ulValue[j];
			sum=sum*m+T[i+j]+carry;
			T[i+j]=(unsigned long)sum;
			carry=(unsigned long)(sum>>32);
		}
		for(j=i+k;j<k*2;j++)
		{
			sum=T[j];
			sum+=carry;
			T[j]=(unsigned long)sum;
			carry=(unsigned long)(sum>>32);
			if(carry==0)break;
		}
	}
	T[k*2]=carry;
	X.m_nLength=k+1;
	for(i=0;i<=k;i++)X.m_ulValue[i]=T[i+k];
	while(X.m_ulValue[X.m_nLength-1]==0)X.m_nLength--;
	if(X.Cmp(B)>=0)X.Mov(X.Sub(B));
	return X;
}

/****************************************************************************************
求模幂
调用方式:N.ModExp(A,B)
返回值:X=N**A%B
****************************************************************************************/
CBigInt CBigInt::ModExp(CBigInt& A, CBigInt& B)
{
	CBigInt X,Y;
	int i,k;
	unsigned long n;
	k=A.m_nLength*32-32;
	n=A.m_ulValue[A.m_nLength-1];
	while(n){n=n>>1;k++;}
	Y.m_nLength=2;
    Y.m_ulValue[1]=1;
	X.Mov(B.m_ulValue[0]);
	X.Mov(X.ModInv(Y));
	X.Mov(Y.Sub(X));
	n=X.m_ulValue[0];
	Y.Mov(0);
	Y.m_nLength=B.m_nLength+1;
	Y.m_ulValue[Y.m_nLength-1]=1;
	X.Mov(Y.Sub(B));
    Y.Mov(ModMul(X,B));
	for(i=k-1;i>=0;i--)
	{
        X.Mov(X.MonPro(X,B,n));
		if((A.m_ulValue[i>>5]>>(i&31))&1)X.Mov(X.MonPro(Y,B,n));
	}
    Y.Mov(1);
	X.Mov(X.MonPro(Y,B,n));
    return X;
}

/****************************************************************************************
测试素数
调用方式:N.TestPrime()
返回值:若N为素数,返回0,否则返回最小质因数,若质因数不可知,返回1
****************************************************************************************/
int CBigInt::TestPrime()
{
    unsigned i,pass;
	if((m_ulValue[0]&1)==0)return 2;
    for(i=0;i<1230;i++){if(Mod(PrimeTable[i])==0)return PrimeTable[i];}
	if((m_nLength==1)&&(m_ulValue[0]<100180081))return 0;
    CBigInt S,A,I,K;
    K.Mov(*this);
	K.m_ulValue[0]--;
    for(i=0;i<5;i++)
    {
        pass=0;
        A.Mov(rand());
		S.Mov(K);
        while((S.m_ulValue[0]&1)==0)
		{
            S.Mov(S.Div(2));
			I.Mov(A.ModExp(S,*this));
			if(I.Cmp(K)==0){pass=1;break;}
		}
		if((I.m_nLength==1)&&(I.m_ulValue[0]==1))pass=1;
		if(pass==0)return 1;
	}
    return 0;
}

/****************************************************************************************
产生随机素数
调用方法:N.FindPrime(bits)
返回值:N被赋值为一个bits位(0x100000000进制长度)的素数
****************************************************************************************/
void CBigInt::FindPrime(int bits)
{
    unsigned i;
    m_nLength=bits;
	for(i=1;i<m_nLength;i++)m_ulValue[i]=rand()*0x10000+rand();
	m_ulValue[m_nLength-1]=m_ulValue[m_nLength-1]|0x80000000;
begin:
    m_ulValue[0]=rand()*0x10000+rand();
	m_ulValue[0]=m_ulValue[0]|3;
    for(i=0;i<500;i++){if(Mod(PrimeTable[i])==0)goto begin;}
    CBigInt S,A;
    S.Mov(*this);
	S.m_ulValue[0]--;
	for(i=0;i<S.m_nLength;i++)
	{
	    S.m_ulValue[i]=S.m_ulValue[i]>>1;
	    if(S.m_ulValue[i+1]&1)S.m_ulValue[i]=S.m_ulValue[i]|0x80000000;
	}
	if(S.m_ulValue[S.m_nLength-1]==0)S.m_nLength--;
    for(i=0;i<5;i++)
	{
        A.Mov(rand());
		A.Mov(A.ModExp(S,*this));
		A.m_ulValue[0]++;
	    if(((A.m_nLength!=1)||(A.m_ulValue[0]!=2))&&(Cmp(A)!=0))goto begin;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -