高精度加法
一位一位的对着加,注意存储进位,小的数加完后把大数剩下的加进来,注意前导零和相加等于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;
}