在本文中我们将采用重复平方乘算法,即如图1:
来解决类似于求a^e mod m的值的问题(a、e、m的位数均可以达到1024位,即计算机无法直接用基本数据类型存储的数据),在代码中一共有6个函数:
第一个为大数减法函数,第二个为大数除法函数,第三个为大数除法函数中的判断辅助函数,第四个为十进制转换为二进制函数,第五个为大数平方函数,第六个为大数乘法函数,有返回值的函数的返回值均是操作数组运算后的位数,代码如下:
#include<stdio.h>
#include<string.h>
int digit;
int a[1024],e[1024],m[1024],b[1024]; //程序操作使用的整数数组
char S_a[1024],S_e[1024],S_m[1024]; //由用户输入的底数、指数、模数
void BigSubtract(int x[],int y[],int len1,int len2);
int BigDivision(int x[],int y[],int len1,int len2);
int judge(int x[],int y[],int len1,int len2);
int Decimal_To_Binary(int e[],int e_length);
int BigSquare(int a[],int a_length);
int BigMult(int a[],int b[],int a_length,int b_length);
int main(){
int i,j;
printf("请先输入操作数(底数)a:");
scanf("%s",S_a);
printf("请先输入操作数(指数)e:");
scanf("%s",S_e);
printf("请先输入操作数(模数)m:");
scanf("%s",S_m);
int a_length=strlen(S_a);
int e_length=strlen(S_e);
int m_length=strlen(S_m);
int b_length;
for(j=0,i=a_length-1;i>=0;i--,j++)
a[j]=S_a[i]-'0';
for(j=0,i=e_length-1;i>=0;i--,j++)
e[j]=S_e[i]-'0';
for(j=0,i=m_length-1;i>=0;i--,j++)
m[j]=S_m[i]-'0';
printf("用户输入的底数a为:"); //人性化提示用户输入的数据是否正确
for(j=a_length-1;j>=0;j--)
printf("%d",a[j]);
printf("\n");
printf("用户输入的指数e为:"); //人性化提示用户输入的数据是否正确
for(j=e_length-1;j>=0;j--)
printf("%d",e[j]);
printf("\n");
printf("用户输入的模数m为:"); //人性化提示用户输入的数据是否正确
for(j=m_length-1;j>=0;j--)
printf("%d",m[j]);
printf("\n");
int eBinaryLength=Decimal_To_Binary(e,e_length); //得到转换为二进制后的数组长度
printf("指数的二进制表示:"); //将指数的二进制数组输出屏幕,以便检验数据是否正确
for(i=eBinaryLength-1;i>=0;i--)
printf("%d",e[i]);
printf("\n");
if (e[0]==0) //初始化需要进行持续操作的A数组和B数组
{
for(i=1;i<1024;i++)
b[i]=0;
b[0]=1;
b_length=1;
}
else
{
for(i=0;i<1024;i++)
b[i]=a[i];
b_length=a_length;
}
for(j=1;j<eBinaryLength;j++) //以二进制数组的长度为循环,进行对应的操作
{
a_length=BigSquare(a,a_length);
a_length=BigDivision(a,m,a_length,m_length); //计算A数组平方再模M数组后的数值
if(e[j]==1)
b_length=BigMult(a,b,a_length,b_length); //如果当前二进制数位为1,则对B数组进行相应的初始化
b_length=BigDivision(b,m,b_length,m_length);
}
printf("用户输入的数据的模运算结果为:"); //打出实验结果
for(i=b_length-1;i>=0;i--)
printf("%d",b[i]);
}
//大数乘法运算
int BigMult(int a[],int b[],int a_length,int b_length){
int i,j,temp;
int a1[1024];
for(i=0;i<=1024;i++)
a1[i]=0;
for(i=0;i<a_length;i++) //进行乘法运算
for(j=0;j<b_length;j++)
a1[i+j]+=a[i]*b[j];
for(i=0;i<1024;i++)
{
temp=a1[i];
a1[i]=(temp%10);
a1[i+1]+=(temp/10);
}
for(i=0;i<1024;i++)
b[i]=a1[i];
for(i=1023;i>=0;i--) //计算B数组的数位
if(b[i])
break;
return i+1;
}
//大数平方乘运算
int BigSquare(int a[],int len1){
int i,j,temp;
int a1[1024];
for(i=0;i<1024;i++)
a1[i]=0;
for(i=0;i<len1;i++) //平方乘
for(j=0;j<len1;j++)
a1[i+j]+=(a[i]*a[j]);
for(i=0;i<1024;i++)
{
temp=a1[i];
a1[i]=(temp%10);
a1[i+1]+=(temp/10);
}
for(i=0;i<1024;i++)
a[i]=a1[i];
for(i=1023;i>=0;i--) //计算A数组的数位
if(a[i]!=0)
break;
return i+1;
}
//十进制转换为二进制
int Decimal_To_Binary(int e[],int e_length){
int m[1024];
int j=0;
int i=0;
for(i=0;i<e_length;i++){
if(e[i]){
m[j]=e[0]%2;
j++;
for(i=0;i<e_length-1;i++) //转换二进制操作
{
e[i]=((e[i+1]%2)*10+e[i])/2;
}
e[e_length-1]=e[e_length-1]/2;
for(i=e_length-1;i>=0;i--)
{
if(i=0&&e[i]==0)
goto next;
}
}
}
next: for(i=0;i<=j;i++) //将转换为二进制的数组复制到全局变量指数数组中
e[i]=m[i];
return j;
}
//大数减法运算
void BigSubtract(int x[],int y[],int len1,int len2){
int i;
for(i=0;i<len1;i++)
{
if(x[i]<y[i])
{
x[i]=x[i]+10-y[i];
x[i+1]--;
}
else
x[i]=x[i]-y[i];
}
for(i=len1;x>=0;i--)
{
if(x[i])
{
digit=i+1;
break;
}
}
}
//大数除法运算
int BigDivision(int a[],int b[],int len1,int len2){
int i,j=0,k=0,t,temp,len;
int z[len1];
int m[1024];
for(i=0;i<1024;i++)
m[i]=b[i];
if(len1<len2) //当被除数位数 小于 除数位数时
{
return len1;
}
else //当被除数位数 大于或者 除数位数时
{
len=len1-len2; //两个大数位数的差值
for(i=len1-1;i>=0;i--) //将除数后补零,使得两个大数位数相同。
{
if(i>=len)
b[i]=b[i-len];
else
b[i]=0;
}
len2=len1; //将两个大数数位相同
digit=len1; //将原被除数位数赋值给digit
for(j=0;j<=len;j++)
{
z[len-j]=0;
while(((temp=judge(a,b,len1,len2))>=0)&&digit>=k)//判断两个数之间的关系以及位数与除数原位数的关系
{
BigSubtract(a,b,len1,len2); //大数减法函数
z[len-j]++; //储存商的每一位
len1=digit; //重新修改被除数的长度
if(len1<len2&&b[len2-1]==0)
len2=len1; //将len1长度赋给len2;
}
if(temp<0)
{
for(i=1;i<len2;i++)
b[i-1]=b[i];
b[i-1]=0;
if(len1<len2)
len2--;
}
}
for(i=len1;i>0;i--)
{
if(a[i])
break;
}
int z=i+1;
for(i=0;i<1024;i++) //计算出b的数位大小
b[i]=m[i];
return z;
}
}
//大数除法运算的辅助函数
int judge(int x[],int y[],int len1,int len2)
{
int i;
if(len1<len2)
return -1;
if(len1==len2) //若两个数位数相等
{
for(i=len1-1;i>=0;i--)
{
if(x[i]==y[i]) //对应位的数相等
continue;
if(x[i]>y[i]) //被除数 大于 除数,返回值为1
return 1;
if(x[i]<y[i]) //被除数 小于 除数,返回值为-1
return -1;
}
return 0; //被除数 等于 除数,返回值为0
}
}