C++ 高精度算法

高精度加法

一位一位的对着加,注意存储进位,小的数加完后把大数剩下的加进来,注意前导零和相加等于0

// 高精度加法 
#include<iostream>
#include<string>
using namespace std;
int res[10000001];//记录结果的数组 
string a,b;
long long k,r,i,j;
bool flag;
int main(){
	cin>>a>>b;
	if(a.size()<b.size()||a.size()==b.size()&&a<b){//把大的字符串放在前面方便操作 
		swap(a,b);
	}
	for(i = a.size() - 1,j = b.size()-1;j>=0;i--,j--){//从低位相加,相加他们的公共位
		res[k++] = (r+a[i]-'0'+b[j]-'0')%10;//相同位的数相加后取个位
		r = (r+a[i]-'0'+b[j]-'0') /10;//记录进位 
	}
	while(i>=0){//再把大数的没有运算的部分相加 
		 res[k++] = (r+a[i]-'0')%10;//位数和进位的相加后取个位
		 r = (r+a[i]-'0')/10;//记录进位
		 i--; 
	}// 
	if(r){
		res[k++] = r;//如果还有进位,进到最高位 
	}
	for(i = k-1;i>=0;i--){//输出 
		if(res[i]!=0||flag){//防止前导0输出的操作. 
			cout<<res[i];
			flag = true;
		} 
	} 
	if(!flag){//如果都为 0,则说明结果为0 
		cout<<0<<endl;
	}
	
	return 0;
}

以上代码是两个正数相加,若有负数,则需要另行判断:

  • 如果两个数都是负数,那么去掉负号,输出结果前加上负号即可。

  • 如果两个数有一个数是负数,先去掉负号,比较大小

如果去掉负号的数大于另一个数,则需要用去掉负号的数减去另一个数,再输出负号(此时用高精度减法)
如果去掉负号的数小于另一个数,则需要用另一个数减去去掉负号的数,(此时用高精度减法)

高精度减法

一位一位的对着减,注意存储借位,小的数减完后把大数剩下的借位减进来,注意前导零和相减等于0

// 高精度减法 
#include<iostream>
#include<string>
using namespace std;
int res[10000001]; //记录结果
string a,b; 
long long k = 0,r = 0,i,j;
bool flag;
int main(){
	cin>>a>>b;
	if(a.size()<b.size()||(a.size()==b.size()&&a<b)){//如果第一个数比第二个数小,说明结果为负数. 
		cout<<"-";
		swap(a,b);
	}
	for(i = a.size() - 1,j = b.size() - 1;j >= 0;i--,j--){
		res[k++] = (a[i]-b[j]-r);// 两个相同位的数相减再减去 借的位数.
		r=0;//清零
		if(res[k-1]<0){//如果是负数,就借一当十,并标记 
			res[k-1]+= 10;
			r = 1;//这次的借的进位 
		} 
	}
	while(i>=0){// 较大的数,剩下的位继续运算 
		res[k++] = a[i] - '0'- r;//减去借的
		r = 0;//清零
		if(res[k-1]<0){//如果是负数,就借一当十,并标记 
			res[k-1]+= 10;
			r = 1;//这次的借的进位 
		} 
		i--; 
	} 
	for(i = k - 1;i>=0;i--){// 从后往前输出 
		if(res[i]!=0 || flag){//防止前导0 
			cout<<res[i];
			flag = true; 
		} 
	}
	if(!flag){
		cout<<0<<endl;//如果都没有输出,说明相减结果为0 ,就输出0 
	}
	return 0; 
}

以上代码是两个正数相减,若有负数,则需要另行判断:

List item

  • 如果两个数都是负数,去掉负号,用后一个数减前一个数。

  • 如果两个数有一个数是负数,先去掉负号,比较大小

如果第一个数是负数,相加,输出负号(此时用高精度加法)
如果第二个数是负数,相加(此时用高精度加法)

高精度乘法

相信大家都手动计算过乘法,就是一个数的每一位乘另一个数的每一位最后相加即可,当然,我们程序也是这样模拟.
这里有一个基本的知识点,相信大家在手写竖式的时候知道,就是
c[i+j] += a[i]+b[j] (因为a和b都是从0下标开始的,如果从下标1开始,就c[i+j-1]+=a[i]+b[j])
在这里插入图片描述

// 高精度乘法
//结果最多 有10000000 位
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string a,b;
int k;
int res[10000001];//'3'-'3'+'48'  '6' - 48
int main() {
	cin>>a>>b;
	reverse(a.begin(),a.end());
	reverse(b.begin(),b.end());
	for(int i = 0; i < a.size(); i++) {
		for(int j = 0; j<b.size(); j++) {
			res[i+j] += (a[i]-48)*(b[j]-48);//
		}
	}
	for(k = 0; k<=a.size()+b.size(); k++) { // n位数 * m位数 最多等于 n+m位数.
		res[k] += res[k-1] / 10;//k位 等于 该位的值加上 进位.
		res[k - 1] %= 10;  // k位计算未必,前面那一位的值就确定了.  直接写该位的个位即可.
	}
	while(!res[k]&&k>=1) {
		k--;//从后往前寻找第一个不为0的位
	}
	while(k>=0) { //输出结果.
		cout<<res[k];
		k--;
	}

	return 0;
}

高精度除法

手动模拟除法过程,每次读到新位 然后除 除数,得到的就是该位的结果。如果除不尽,就用0代替. 每次的余数用于下一轮的计算.

#include<bits/stdc++.h>
using namespace std;
int res[10000001];
string s;
long long k = 0,a,b,i;
bool flag;
int main(){
	cin>>s>>b;//输入被除数,除数 
	for(i = 0; i < s.size();i++){
		a = a*10+s[i]-'0';//加上被除数的这一位.
		res[k++] = a / b;
		a %= b; // 求余下一轮乘10+再加一位继续乘. 
	} 
	for(i = 0; i < k; i++){//输出结果 
		if(res[i]!=0||flag){
			cout<<res[i];
			flag = true;//防止前导0. 
		} 
	} 
	if(!flag){
		cout<<0<<endl;//如果都没有输出,则说明相除结果为0 
	} 
	return 0; 
	
}

以上代码是两个正数相除,若有负数,则需要另行判断:

  • 如果两个数都是负数,去掉负号,不管他。

  • 如果两个数有一个数是负数,去掉负号,输出时加上。

高精度求余

这个和高精度除法差不多,不需要记录和输出商就差不多

#include<bits/stdc++.h>
using namespace std;
//int res[10000001];
string s;
long long k = 0,a,b,i;
bool flag;
int main(){
	cin>>s>>b;//输入被除数,除数 
	for(i = 0; i < s.size();i++){
		a = a*10+s[i]-'0';//加上被除数的这一位.
		//res[k++] = a / b;
		a %= b; // 求余下一轮乘10+再加一位继续乘. 
	} 
	cout<<a<<endl; 
	
	return 0; 
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值