NOIP学习小站
西安交通大学附属中学航天学校

高精度运算——高精度正整数加法

两个高精度数按照前面的规则存储到数组中后,只需要从低位到高位按位相加就能实现高精度数的加法。在按位相加的过程中需要处理进位:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/* 高精度加法
** ma+mb → mc
**/
void add(int ma[],int mb[],int mc[]){
int x = 0; //进位
mc[0] = 0; //结果的位数
//从低位到高位按位相加
for(int i=1;i<=ma[0] || i<=mb[0];i++){
mc[i] = ma[i]+mb[i]+x; //从低位到高位按位相加(考虑了进位)
if(mc[i]>=10) x = 1,mc[i] -= 10;
else x = 0; //else部分千万不能少
mc[0]++; //位数+1
}
//最高位相加后出现进位
if(x>0) mc[++mc[0]]=x;
}
/* 高精度加法 ** ma+mb → mc **/ void add(int ma[],int mb[],int mc[]){ int x = 0; //进位 mc[0] = 0; //结果的位数 //从低位到高位按位相加 for(int i=1;i<=ma[0] || i<=mb[0];i++){ mc[i] = ma[i]+mb[i]+x; //从低位到高位按位相加(考虑了进位) if(mc[i]>=10) x = 1,mc[i] -= 10; else x = 0; //else部分千万不能少 mc[0]++; //位数+1 } //最高位相加后出现进位 if(x>0) mc[++mc[0]]=x; }
/* 高精度加法 
** ma+mb → mc 
**/
void add(int ma[],int mb[],int mc[]){
    int x = 0;    //进位 
    mc[0] = 0;    //结果的位数
    
    //从低位到高位按位相加 
    for(int i=1;i<=ma[0] || i<=mb[0];i++){
        mc[i] = ma[i]+mb[i]+x;    //从低位到高位按位相加(考虑了进位)
		if(mc[i]>=10) x = 1,mc[i] -= 10; 
		else x = 0;               //else部分千万不能少
        mc[0]++;                  //位数+1 
    }
    
    //最高位相加后出现进位 
    if(x>0) mc[++mc[0]]=x;
}

当然也可以使用整除直接计算进位,使用模运算修正每位的数字:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/* 高精度加法
** ma+mb → mc
**/
void add(int ma[],int mb[],int mc[]){
int x = 0; //进位
mc[0] = 0; //结果的位数
//从低位到高位按位相加
for(int i=1;i<=ma[0] || i<=mb[0];i++){
mc[i] = ma[i]+mb[i]+x; //从低位到高位按位相加(考虑了进位)
x = mc[i]/10; //计算进位
mc[i] %= 10; //修正该位结果
mc[0]++; //位数+1
}
//最高位相加后出现进位
if(x>0) mc[++mc[0]]=x;
}
/* 高精度加法 ** ma+mb → mc **/ void add(int ma[],int mb[],int mc[]){ int x = 0; //进位 mc[0] = 0; //结果的位数 //从低位到高位按位相加 for(int i=1;i<=ma[0] || i<=mb[0];i++){ mc[i] = ma[i]+mb[i]+x; //从低位到高位按位相加(考虑了进位) x = mc[i]/10; //计算进位 mc[i] %= 10; //修正该位结果 mc[0]++; //位数+1 } //最高位相加后出现进位 if(x>0) mc[++mc[0]]=x; }
/* 高精度加法 
** ma+mb → mc 
**/
void add(int ma[],int mb[],int mc[]){
	int x = 0;	//进位 
	mc[0] = 0;	//结果的位数
	
	//从低位到高位按位相加 
	for(int i=1;i<=ma[0] || i<=mb[0];i++){
		mc[i] = ma[i]+mb[i]+x;	//从低位到高位按位相加(考虑了进位) 
		x = mc[i]/10;			 //计算进位 
		mc[i] %= 10;			  //修正该位结果 
		mc[0]++;				  //位数+1 
	}
	
	//最高位相加后出现进位  
	if(x>0) mc[++mc[0]]=x;
}

也可以实现高精度自加:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/* 高精度自加
** ma+mb → ma
**/
void add(int ma[],int mb[]){
int x = 0; //进位
int n = 0; //用变量n记录结果的位数
for(int i=1;i<=ma[0] || i<=mb[0];i++){
ma[i] = ma[i]+mb[i]+x; //从低位到高位按位相加(考虑了进位)
x = ma[i]/10; //计算进位
ma[i] = ma[i]%10; //修正该位结果
n++; //位数+1
}
ma[0] = n; //修改位数
//最高位相加后出现进位
if(x>0) ma[++ma[0]] = x;
}
/* 高精度自加 ** ma+mb → ma **/ void add(int ma[],int mb[]){ int x = 0; //进位 int n = 0; //用变量n记录结果的位数 for(int i=1;i<=ma[0] || i<=mb[0];i++){ ma[i] = ma[i]+mb[i]+x; //从低位到高位按位相加(考虑了进位) x = ma[i]/10; //计算进位 ma[i] = ma[i]%10; //修正该位结果 n++; //位数+1 } ma[0] = n; //修改位数 //最高位相加后出现进位 if(x>0) ma[++ma[0]] = x; }
/* 高精度自加 
** ma+mb → ma
**/ 
void add(int ma[],int mb[]){
	int x = 0;	//进位 
	int n = 0;	//用变量n记录结果的位数

	for(int i=1;i<=ma[0] || i<=mb[0];i++){
		ma[i] = ma[i]+mb[i]+x;	//从低位到高位按位相加(考虑了进位) 
		x = ma[i]/10;			 //计算进位 
		ma[i] = ma[i]%10;		 //修正该位结果 
		n++;					  //位数+1 
	}
	ma[0] = n;	//修改位数 

	//最高位相加后出现进位 
	if(x>0) ma[++ma[0]] = x;
}

完整的测试程序如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#include<cstdio>
#include<cstring>
#define N 10010
char s1[N],s2[N];
int a[N],b[N],c[N];
/***********************************************************************
** 函数申明
***********************************************************************/
void convert(char s[],int arr[]); //高精度整数字符串格式化存储到数组
void print(int arr[]); //输出存储在数组中的高精度整数
void add(int ma[],int mb[],int mc[]); //高精度加法 ma+mb → mc
void add(int ma[],int mb[]); //高精度自加 ma+mb → ma
/**********************************************************************/
//函数申明结束
/* 高精度正整数字符串格式化存储到数组
** arr[0]保存数字位数
** arr[1],arr[2],...,arr[arr[0]]从低位到高位依次存储高精度整数
**/
void convert(char s[],int arr[]){
memset(arr,0,N*sizeof(int)); //数组arr全部元素初始化为0
for(int i=strlen(s)-1;i>=0;i--){
arr[0]++;
arr[arr[0]] = s[i]-'0';
}
}
/* 输出存储在数组中的高精度整数
**/
void print(int arr[]){
for(int i=arr[0];i>=1;i--) printf("%d",arr[i]);
}
/* 高精度加法
** ma+mb → mc
**/
void add(int ma[],int mb[],int mc[]){
int x = 0; //进位
mc[0] = 0; //结果的位数
//从低位到高位按位相加
for(int i=1;i<=ma[0] || i<=mb[0];i++){
mc[i] = ma[i]+mb[i]+x; //从低位到高位按位相加(考虑了进位)
x = mc[i]/10; //计算进位
mc[i] %= 10; //修正该位结果
mc[0]++; //位数+1
}
//最高位相加后出现进位
if(x>0) mc[++mc[0]]=x;
}
/* 高精度自加
** ma+mb → ma
**/
void add(int ma[],int mb[]){
int x = 0; //进位
int n = 0; //用变量n记录结果的位数
for(int i=1;i<=ma[0] || i<=mb[0];i++){
ma[i] = ma[i]+mb[i]+x; //从低位到高位按位相加(考虑了进位)
x = ma[i]/10; //计算进位
ma[i] = ma[i]%10; //修正该位结果
n++; //位数+1
}
ma[0] = n; //修改位数
//最高位相加后出现进位
if(x>0) ma[++ma[0]] = x;
}
int main()
{
//将高精度正整数按照字符串的方式输入存储
scanf("%s%s",s1,s2);
//遵循存储规则,得到存储高精度正整数的数组
convert(s1,a);
convert(s2,b);
printf("输入的第1个高精度正整数是:\n");
print(a);
printf("\n\n");
printf("输入的第2个高精度正整数是:\n");
print(b);
printf("\n\n");
add(a,b,c);
printf("输入的两个高精度正整数的和是:\n");
print(c);
return 0;
}
#include<cstdio> #include<cstring> #define N 10010 char s1[N],s2[N]; int a[N],b[N],c[N]; /*********************************************************************** ** 函数申明 ***********************************************************************/ void convert(char s[],int arr[]); //高精度整数字符串格式化存储到数组 void print(int arr[]); //输出存储在数组中的高精度整数 void add(int ma[],int mb[],int mc[]); //高精度加法 ma+mb → mc void add(int ma[],int mb[]); //高精度自加 ma+mb → ma /**********************************************************************/ //函数申明结束 /* 高精度正整数字符串格式化存储到数组 ** arr[0]保存数字位数 ** arr[1],arr[2],...,arr[arr[0]]从低位到高位依次存储高精度整数 **/ void convert(char s[],int arr[]){ memset(arr,0,N*sizeof(int)); //数组arr全部元素初始化为0 for(int i=strlen(s)-1;i>=0;i--){ arr[0]++; arr[arr[0]] = s[i]-'0'; } } /* 输出存储在数组中的高精度整数 **/ void print(int arr[]){ for(int i=arr[0];i>=1;i--) printf("%d",arr[i]); } /* 高精度加法 ** ma+mb → mc **/ void add(int ma[],int mb[],int mc[]){ int x = 0; //进位 mc[0] = 0; //结果的位数 //从低位到高位按位相加 for(int i=1;i<=ma[0] || i<=mb[0];i++){ mc[i] = ma[i]+mb[i]+x; //从低位到高位按位相加(考虑了进位) x = mc[i]/10; //计算进位 mc[i] %= 10; //修正该位结果 mc[0]++; //位数+1 } //最高位相加后出现进位 if(x>0) mc[++mc[0]]=x; } /* 高精度自加 ** ma+mb → ma **/ void add(int ma[],int mb[]){ int x = 0; //进位 int n = 0; //用变量n记录结果的位数 for(int i=1;i<=ma[0] || i<=mb[0];i++){ ma[i] = ma[i]+mb[i]+x; //从低位到高位按位相加(考虑了进位) x = ma[i]/10; //计算进位 ma[i] = ma[i]%10; //修正该位结果 n++; //位数+1 } ma[0] = n; //修改位数 //最高位相加后出现进位 if(x>0) ma[++ma[0]] = x; } int main() { //将高精度正整数按照字符串的方式输入存储 scanf("%s%s",s1,s2); //遵循存储规则,得到存储高精度正整数的数组 convert(s1,a); convert(s2,b); printf("输入的第1个高精度正整数是:\n"); print(a); printf("\n\n"); printf("输入的第2个高精度正整数是:\n"); print(b); printf("\n\n"); add(a,b,c); printf("输入的两个高精度正整数的和是:\n"); print(c); return 0; }
#include<cstdio>
#include<cstring>
#define N 10010
char s1[N],s2[N];
int a[N],b[N],c[N];

/***********************************************************************
** 函数申明
***********************************************************************/
void convert(char s[],int arr[]);		//高精度整数字符串格式化存储到数组 
void print(int arr[]);				   //输出存储在数组中的高精度整数

void add(int ma[],int mb[],int mc[]);	//高精度加法 ma+mb → mc
void add(int ma[],int mb[]);			 //高精度自加 ma+mb → ma
/**********************************************************************/
//函数申明结束


/* 高精度正整数字符串格式化存储到数组
** arr[0]保存数字位数
** arr[1],arr[2],...,arr[arr[0]]从低位到高位依次存储高精度整数 
**/
void convert(char s[],int arr[]){ 
	memset(arr,0,N*sizeof(int));		//数组arr全部元素初始化为0 
	for(int i=strlen(s)-1;i>=0;i--){
		arr[0]++;
		arr[arr[0]] = s[i]-'0';
	}
}

/* 输出存储在数组中的高精度整数 
**/ 
void print(int arr[]){
	for(int i=arr[0];i>=1;i--) printf("%d",arr[i]);
}

/* 高精度加法 
** ma+mb → mc 
**/
void add(int ma[],int mb[],int mc[]){
	int x = 0;	//进位 
	mc[0] = 0;	//结果的位数
	
	//从低位到高位按位相加 
	for(int i=1;i<=ma[0] || i<=mb[0];i++){
		mc[i] = ma[i]+mb[i]+x;	//从低位到高位按位相加(考虑了进位) 
		x = mc[i]/10;			 //计算进位 
		mc[i] %= 10;			  //修正该位结果 
		mc[0]++;				  //位数+1 
	}
	
	//最高位相加后出现进位  
	if(x>0) mc[++mc[0]]=x;
}

/* 高精度自加 
** ma+mb → ma
**/ 
void add(int ma[],int mb[]){
	int x = 0;	//进位 
	int n = 0;	//用变量n记录结果的位数

	for(int i=1;i<=ma[0] || i<=mb[0];i++){
		ma[i] = ma[i]+mb[i]+x;	//从低位到高位按位相加(考虑了进位) 
		x = ma[i]/10;			 //计算进位 
		ma[i] = ma[i]%10;		 //修正该位结果 
		n++;					  //位数+1 
	}
	ma[0] = n;	//修改位数 

	//最高位相加后出现进位 
	if(x>0) ma[++ma[0]] = x;
}

int main()
{
	//将高精度正整数按照字符串的方式输入存储 
	scanf("%s%s",s1,s2);
	
	//遵循存储规则,得到存储高精度正整数的数组 
	convert(s1,a);
	convert(s2,b);
	
	printf("输入的第1个高精度正整数是:\n");
	print(a);	
	printf("\n\n");
	
	printf("输入的第2个高精度正整数是:\n");
	print(b);
	printf("\n\n");

	add(a,b,c);	
	printf("输入的两个高精度正整数的和是:\n");
	print(c);
	return 0;
}