大数的加减乘除法的实现(1)
在代码编程的过程中,经常会涉及到一些比较大的数的运算,当他们超出long long int 等基本类型所能表示的范围时,就会造成溢出,整型一般的加减乘除法已无法实现了,因为有可能输入的数都已经超出范围了,更别说得到正确的结果了。这时候,就需要自己写一个程序来实现了。
大数的输入
当一个数字超出基本类型所能表示的范围时,可以以字符串的形式输入。运算时,再按位运算即可。如:当数字与数位无关,只与个数位上的数字有关时,可以以字符串的形式输入,以整型数组的形式存储。
string a;
int b[200];
cin>>a; //以字符串的形式输入
for(int i=0;a[i]!='\0';i++){
b[i]=a[i]-'0'; //以整型数组的形式存储,或b[i]=a[i]-48;
}
大数的加法
//大数相加的实现
//用字符串来表示整型
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string add(string a,string b){ //加法函数
if(a.find_first_not_of('0')==string::npos) //string::npos指如果没找到,返回一个标志;这里可以指;如果a全部为零,则进入
a="0";
else a=a.substr(a.find_first_not_of('0')); //把字符串前面的零全部去掉,因为数字前面没有零
if(b.find_first_not_of('0')==string::npos)
b="0";
else b=b.substr(b.find_first_not_of('0'));
//翻转,低位在左边,这样a,b的数位就对齐了
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
//len是和的长度,所以它必须比a,b中的最长的长度还要长,故加上10,保证不会溢出
long long lenA = a.length();
long long lenB = b.length();
long long len =max(lenA,lenB)+10;
//初始化长度为len,字符全部为‘0’的ans字符串存储和
string ans(len,'0');
//把a搬到ans中
for(int i=0;i<lenA;i++){
ans[i]=a[i];
}
int tmp=0; //tmp是上一位相加后的进位
for(int i=0;i<len;i++){
if(i<lenB){ //当b还有数位时
tmp+=(ans[i]-'0')+(b[i]-'0');
}
else{ //当b没有数位时
tmp+=(ans[i]-'0');
}
ans[i]=tmp%10+'0'; //本位
tmp/=10; //下一位的进位
}
//翻转回来
reverse(ans.begin(),ans.end());
//字符串前面的零全部去掉,因为数字前面没有零
return ans.substr(ans.find_first_not_of('0'));
}
int main(){
string a,b;
cin>>a;
cin>>b;
cout<<add(a,b)<<endl;
return 0;
}
大数的减法
//大数相减的实现
//用字符串表示整型
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
string subtract(string a,string b){ //减法函数
if(a.find_first_not_of('0')==string::npos){ //如果a等于0
if(b.find_first_not_of('0')==string::npos){ //b也等于0
return "0";
}else{ //b不等于0
b=b.substr(b.find_first_not_of('0'));
string ans(b.length()+1,'-'); //ans=-b
for(int i=1;i<b.length()+1;i++)
ans[i]=b[i-1];
return ans;
}
}
if(b.find_first_not_of('0')==string::npos){ //如果b等于0
return a.substr(a.find_first_not_of('0'));
}
a=a.substr(a.find_first_not_of('0')); //去掉a,b字符串前面的零
b=b.substr(b.find_first_not_of('0'));
bool flag=false; //标记a,b的比较,a<b为true,结果为负
if( a.length()<b.length() || a.length()==b.length()&&a<b){ //如果b>a,交换
flag=true;
string tmp = b; //a,b交换
b=a;
a=tmp;
}
//翻转,低位在左边,先运算
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
//按位做减法
for(int i=0;i<b.length();++i){
if(a[i]>=b[i]){ //本位够减
a[i]=a[i]-b[i]+'0';
}else{ //不够减,需借位
int k=1;
while(a[i+k]=='0'){ //如果下一位只有0,借出1,置9,再往后一位借1
a[i+k]='9';
k++;
}
a[i+k]=a[i+k]-'1'+'0'; //i+k位借出了1
a[i]=(a[i]-'0')+10-(b[i]-'0')+'0'; //i位借来了10,相减
}
}
reverse(a.begin(),a.end()); //翻转回来
if(a.find_first_not_of('0')==string::npos) //string::npos指如果没找到,返回一个标志;这里指;如果a全部为零,则进入
return "0";
if(flag) { //负数的处理
string ans(a.length()+1,'0'); //声明一个长度为a.length()+1,字符全部为‘0’的字符串
ans[0]='-'; //加上负号
for(int i=a.length()+1;i>0;i--){ //将a赋值给ans,a的第1位放到ans的第2位,以此类推 。。。
ans[i]=a[i-1];
} //字符串前面全部去掉零
return ans.substr(ans.find_first_not_of('0'));
}
return a.substr(a.find_first_not_of('0'));
}
int main(){
string a,b;
cin>>a;
cin>>b;
cout<<subtract(a,b)<<endl;
return 0;
}
这里加减法输入的大数只限于正整数,涉及负数的运算,以后更新。如果还少了其他情况,希望读者可以提出来!