高精度

用字符串存储,模拟四则运算

为了方便个位对齐,把字符串倒着转化到另一个int数组中,高位补零(初始化为0),数组中的元素代表原数中的某一位,输出需要倒序输出

高精度加法

  • 结果数最大长度max(la,lb)+1
  • 先进位再保留余数
int a[maxNum],b[maxNum],c[maxNum];    //c是结果数组
string s1,s2;
int la,lb,lc;


void add(){
	cin>>s1>>s2;
	la=s1.length();
	lb=s2.length();
	lc=max(la,lb)+1;    //最大结果长度
	//倒序存
	for(int i=0;i<la;i++){
		a[i]=s1[la-1-i]-'0';
	}
	for(int i=0;i<lb;i++){
		b[i]=s2[lb-1-i]-'0';
	}
	//模拟加法
	for(int i=0;i<max(la,lb);i++){
		c[i]+=a[i]+b[i];
		c[i+1]+=c[i]/10;
		c[i]=c[i]%10;
	}
	//去掉前导零
	lc--;    //把lc转化成最高位下标
	while(c[lc]==0&&lc>0)lc--;
	//输出
	for(int i=lc;i>=0;i--){
		cout<<c[i];
	}
	cout<<endl;
}

高精度减法

  • 结果数最大长度max(la,lb)
  • 先比较两个数,保证大减小
  • 先借位,再相减(或先相减,再借位),最高位不会借位
int a[maxNum],b[maxNum],c[maxNum];    //c是结果数组
string s1,s2;
int la,lb,lc;

void sub(){
	cin>>s1>>s2;
	lc=max(la,lb);
	if(la<lb||(la==lb&&s1<s2)){
		cout<<'-';    //先输出负号
		swap(s1,s2);
	}
	la=s1.length();
	lb=s2.length();
	for(int i=0;i<la;i++){
		a[i]=s1[la-1-i]-'0';
	}
	for(int i=0;i<lb;i++){
		b[i]=s2[lb-1-i]-'0';
	}
	for(int i=0;i<lc;i++){
		if(a[i]<b[i]){    //不够就借位
			a[i]+=10;
			a[i+1]--;
		}
		c[i]=a[i]-b[i];
		/*    先相减再借位,不会改动a数组
		c[i]+=a[i]-b[i];
		if(c[i]<0){
			c[i]+=10;
			c[i+1]--;
		}
		*/
	}
	//去掉前导零
	lc--;    //把lc转化成最高位下标
	while(c[lc]==0&&lc>0)lc--;
	//输出
	for(int i=lc;i>=0;i--){
		cout<<c[i];
	}
	cout<<endl;
}

高精度乘法

  • 结果数最大长度为la+lb
  • 两层循环,一层a的每位,一层b的每位
  • 错位相乘c[i+j]+=a[i]+b[j]
  • 最后再处理进位
int a[maxNum],b[maxNum],c[2*maxNum];    //c是结果数组
string s1,s2;
int la,lb,lc;

void multi(){
	cin>>s1>>s2;
	la=s1.length();
	lb=s2.length();
	lc=la+lb;
	for(int i=0;i<la;i++){
		a[i]=s1[la-1-i]-'0';
	}
	for(int i=0;i<lb;i++){
		b[i]=s2[lb-1-i]-'0';
	}
	for(int i=0;i<la;i++){
		for(int j=0;j<lb;j++){
			c[i+j]+=a[i]*b[j];
		}
	}
	for(int i=0;i<lc;i++){
		c[i+1]+=c[i]/10;
		c[i]=c[i]%10;
	}
	lc--;
	while(c[lc]==0&&lc>0)lc--;
	for(int i=lc;i>=0;i--){
		cout<<c[i];
	}
	cout<<endl;
}

高精度除法

结果向下取整

  • 较小的数除以较大的数结果是0
  • 结果数长度为la-lb+1
  • 从数组下标1开始存,下标0存数的长度
  • 用temp数组存b数,让b的最低位与c的要计算的位对齐,低位补零
  • 减法模拟除法
  • 若除数或被除数有前导零需要先去掉前导零
int a[maxNum],b[maxNum],c[maxNum];
int temp[maxNum];    //临时数组
//int la,lb,lc;

bool cmp(int *x,int *y){    //x大于等于y返回true
	if(x[0]>y[0])return true;
	else if(x[0]<y[0])return false;
	else {
		for(int i=x[0];i>=1;i--){
			if(x[i]>y[i])return true;
			else if(x[i]<y[i])return false;
		}
		return true;
	}
}

void sub(int *x,int *y){
	for(int i=1;i<=x[0];i++){
		if(x[i]<y[i]){    //借位
			x[i]+=10;
			x[i+1]--;
		}
		x[i]-=y[i];
	}
	//去掉前导零得到结果位数
	int i=x[0];
	while(x[i]==0&&i>1)i--;
	x[0]=i;
}

void divi(){
	cin>>s1>>s2;
	a[0]=s1.length;
	b[0]=s2.length;
	for(int i=1;i<=a[0];i++){
		a[i]=s1[a[0]-i]-'0';
	}
	for(int i=1;i<=b[0];i++){
		b[i]=s2[b[0]-i]-'0';
	}
	if(cmp(a,b)==false){    //小数除大数直接输出0
		cout<<0<<endl;
		return;
	}
	c[0]=a[0]-b[0]+1;
	for(int i=c[0];i>=1;i--){    //从高位开始计算商的每一位
		memset(temp,0,sizeof(temp));
		//把b存在temp的高位
		for(int j=1;j<=b[0];j++){
			temp[i+j-1]=b[j];
		}
		temp[0]=i+b[0]-1;
		while(cmp(a,temp)){
			sub(a,t);
			c[i]++;
		}
	}
	int i=c[0];
	while(c[i]==0&&i>1)i--;
	c[0]=i;
	for(int j=c[0];j>=1;j--){
		cout<<c[j];
	}
	cout<<endl;
}
posted @ 2026-04-04 09:16  mofei1116  阅读(2)  评论(0)    收藏  举报