📄 bigint.cpp
字号:
for(i=Z.m_nLength-1;i>=len;i--)Z.m_ulValue[i]=Z.m_ulValue[i-len];
for(i=0;i<len;i++)Z.m_ulValue[i]=0;
}
X.Mov(X.Add(Z));
Y.Mov(Y.Sub(A.Mul(Z)));
}
return X;
}
CBigInt CBigInt::Div(unsigned long A)
{
CBigInt X;
X.Mov(*this);
if(X.m_nLength==1){X.m_ulValue[0]=X.m_ulValue[0]/A;return X;}
unsigned __int64 div,mul;
unsigned long carry=0;
for(int i=X.m_nLength-1;i>=0;i--)
{
div=carry;
div=(div<<32)+X.m_ulValue[i];
X.m_ulValue[i]=(unsigned long)(div/A);
mul=(div/A)*A;
carry=(unsigned long)(div-mul);
}
if(X.m_ulValue[X.m_nLength-1]==0)X.m_nLength--;
return X;
}
/****************************************************************************************
大数求模
调用形式:N.Mod(A)
返回值:N%A
****************************************************************************************/
CBigInt CBigInt::Mod(CBigInt& A)
{
CBigInt X,Y;
unsigned __int64 div,num;
unsigned long carry=0;
unsigned i,len;
X.Mov(*this);
while(X.Cmp(A)>=0)
{
div=X.m_ulValue[X.m_nLength-1];
num=A.m_ulValue[A.m_nLength-1];
len=X.m_nLength-A.m_nLength;
if((div==num)&&(len==0)){X.Mov(X.Sub(A));break;}
if((div<=num)&&len){len--;div=(div<<32)+X.m_ulValue[X.m_nLength-2];}
div=div/(num+1);
Y.Mov(div);
Y.Mov(A.Mul(Y));
if(len)
{
Y.m_nLength+=len;
for(i=Y.m_nLength-1;i>=len;i--)Y.m_ulValue[i]=Y.m_ulValue[i-len];
for(i=0;i<len;i++)Y.m_ulValue[i]=0;
}
X.Mov(X.Sub(Y));
}
return X;
}
unsigned long CBigInt::Mod(unsigned long A)
{
if(m_nLength==1)return(m_ulValue[0]%A);
unsigned __int64 div;
unsigned long carry=0;
for(int i=m_nLength-1;i>=0;i--)
{
div=m_ulValue[i];
div+=carry*0x100000000;
carry=(unsigned long)(div%A);
}
return carry;
}
/****************************************************************************************
从字符串按设定进制格式输入到大数
调用格式:N.Get(str,sys)
返回值:N被赋值为相应大数
sys即进制数
****************************************************************************************/
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]-61;
else k=62;
//if ((str[i]>=42)&&(str[i]<=122)) k=str[i]-42;
//else k=62;
Mov(Add(k));
}
}
/****************************************************************************************
从字符串按设定进制格式输入到大数
调用格式:N.GetLast(str,sys)
返回值:N被赋值为相应大数
sys即进制数
****************************************************************************************/
void CBigInt::GetLast(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));
}
}
/****************************************************************************************
将大数按设定进制格式输出为字符串
调用格式:N.Put(str,sys)
返回值:无,参数str被赋值为N的sys进制字符串
sys即进制数
****************************************************************************************/
void CBigInt::Put(CString& str, unsigned int system)
{
if((m_nLength==1)&&(m_ulValue[0]==0)){str="0";return;}
str="";
CString t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ";
int a;
char ch;
CBigInt X;
X.Mov(*this);
while(X.m_ulValue[X.m_nLength-1]>0)
{
a=X.Mod(system);
ch=t[a];
str.Insert(0,ch);
X.Mov(X.Div(system));
}
}
/****************************************************************************************
求不定方程ax-by=1的最小整数解
调用方式:N.Euc(A)
返回值:X,满足:NX mod A=1
****************************************************************************************/
CBigInt CBigInt::Euc(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.RsaTrans(A,B)
返回值:X=N^A MOD B
****************************************************************************************/
CBigInt CBigInt::RsaTrans(CBigInt& A, CBigInt& B)
{
CBigInt X,Y;
int i,j,k;
unsigned n;
unsigned long num;
k=A.m_nLength*32-32;
num=A.m_ulValue[A.m_nLength-1];
while(num){num=num>>1;k++;}
X.Mov(*this);
for(i=k-2;i>=0;i--)
{
Y.Mov(X.Mul(X.m_ulValue[X.m_nLength-1]));
Y.Mov(Y.Mod(B));
for(n=1;n<X.m_nLength;n++)
{
for(j=Y.m_nLength;j>0;j--)Y.m_ulValue[j]=Y.m_ulValue[j-1];
Y.m_ulValue[0]=0;
Y.m_nLength++;
Y.Mov(Y.Add(X.Mul(X.m_ulValue[X.m_nLength-n-1])));
Y.Mov(Y.Mod(B));
}
X.Mov(Y);
if((A.m_ulValue[i>>5]>>(i&31))&1)
{
Y.Mov(Mul(X.m_ulValue[X.m_nLength-1]));
Y.Mov(Y.Mod(B));
for(n=1;n<X.m_nLength;n++)
{
for(j=Y.m_nLength;j>0;j--)Y.m_ulValue[j]=Y.m_ulValue[j-1];
Y.m_ulValue[0]=0;
Y.m_nLength++;
Y.Mov(Y.Add(Mul(X.m_ulValue[X.m_nLength-n-1])));
Y.Mov(Y.Mod(B));
}
X.Mov(Y);
}
}
return X;
}
/****************************************************************************************
拉宾米勒算法测试素数 正确率达99.99%
调用方式:N.Rab()
返回值:若N为素数,返回1,否则返回0
****************************************************************************************/
int CBigInt::Rab()
{
unsigned i,j,pass;
CBigInt S,A,I,K;
K.Mov(*this);
K.m_ulValue[0]--;
for(i=0;i<5;i++)
{
pass=0;
A.Mov(rand()*rand());
S.Mov(K);
while((S.m_ulValue[0]&1)==0)
{
for(j=0;j<S.m_nLength;j++)
{
S.m_ulValue[j]=S.m_ulValue[j]>>1;
if(S.m_ulValue[j+1]&1)S.m_ulValue[j]=S.m_ulValue[j]|0x80000000;
}
if(S.m_ulValue[S.m_nLength-1]==0)S.m_nLength--;
I.Mov(A.RsaTrans(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 0;
}
return 1;
}
/****************************************************************************************
产生随机素数
调用方法:N.GetPrime(bits)
返回值:N被赋值为一个bits位(0x100000000进制长度)的素数
****************************************************************************************/
void CBigInt::GetPrime(int bits)
{
unsigned i;
m_nLength=bits;
begin:
for(i=0;i<m_nLength;i++)m_ulValue[i]=rand()*0x10000+rand();
m_ulValue[0]=m_ulValue[0]|1;
for(i=m_nLength-1;i>0;i--)
{
m_ulValue[i]=m_ulValue[i]<<1;
if(m_ulValue[i-1]&0x80000000)m_ulValue[i]++;
}
m_ulValue[0]=m_ulValue[0]<<1;
m_ulValue[0]++;
for(i=0;i<550;i++){if(Mod(PrimeTable[i])==0)goto begin;}
CBigInt K;
K.Mov(*this);
if(K.Rab()==0) goto begin;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -